From 4ac5dd4c88324f99cb6827283ad85bb9718abbeb Mon Sep 17 00:00:00 2001 From: "Max P." Date: Fri, 30 May 2025 11:44:09 +0200 Subject: [PATCH] feat(i18n): support loading JSONC translation files - Adds support for `.jsonc` format alongside `.json` for locale files - Prioritizes `.jsonc` format when both file types are available --- src/i18n/i18n.ts | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/i18n/i18n.ts b/src/i18n/i18n.ts index 7cce973..4e19c9f 100644 --- a/src/i18n/i18n.ts +++ b/src/i18n/i18n.ts @@ -1,3 +1,5 @@ +import { parse as parseJsonc } from '@std/jsonc'; + /** * Initializes the i18n module by loading * the appropriate locale file based on the system language. @@ -15,29 +17,35 @@ let translations: Record = {}; /** * Loads the translation file for the specified locale. * - * Expects a JSON file in the same directory named like `de.json` or `en.json`. + * Accepts both `.jsonc` (JSON with comments) and plain `.json`. + * When both exist, `.jsonc` takes precedence. * Falls back to English ('en') if the specified file does not exist. * * @param locale - The language code (e.g., 'de', 'en') to load * @returns Promise that resolves once the translations have been loaded */ export async function loadLocale(locale: string): Promise { - try { - const localeUrl = new URL(`./${locale}.json`, import.meta.url); - const file = await Deno.readTextFile(localeUrl); - translations = JSON.parse(file); - } catch (err) { - if (err instanceof Deno.errors.NotFound) { - console.warn( - `Locale '${locale}' not found – falling back to 'en'.`, - ); - if (locale !== 'en') { - await loadLocale('en'); + const extensions = ['jsonc', 'json']; + for (const ext of extensions) { + try { + const localeUrl = new URL(`./${locale}.${ext}`, import.meta.url); + const raw = await Deno.readTextFile(localeUrl); + // parseJsonc tolerates both pure JSON and JSONC, so we can use it for either. + translations = parseJsonc(raw) as Record; + return; + } catch (err) { + if (err instanceof Deno.errors.NotFound) { + // Continue with next extension. + continue; } - } else { - console.error('Error loading translation file:', err); + console.error(`Error parsing locale '${locale}.${ext}':`, err); + break; } } + if (locale !== 'en') { + console.warn(`Locale '${locale}' not found – falling back to 'en'.`); + await loadLocale('en'); + } } /**