diff --git a/.gitignore b/.gitignore index a1bdf21a..c586d40c 100644 --- a/.gitignore +++ b/.gitignore @@ -43,4 +43,3 @@ test-results/ # Localization Resources /server/locales/*.json !/server/locales/en.json -/server/locales/metadata.mjs diff --git a/server/locales/metadata.mjs b/server/locales/metadata.mjs index 00fd63db..a3c8cc7c 100644 --- a/server/locales/metadata.mjs +++ b/server/locales/metadata.mjs @@ -2,6 +2,15 @@ const localazyMetadata = { projectUrl: "https://localazy.com/p/wiki", baseLocale: "en", languages: [ + { + language: "de", + region: "", + script: "", + isRtl: false, + name: "German", + localizedName: "Deutsch", + pluralType: (n) => { return (n===1) ? "one" : "other"; } + }, { language: "en", region: "", @@ -10,6 +19,42 @@ const localazyMetadata = { name: "English", localizedName: "English", pluralType: (n) => { return (n===1) ? "one" : "other"; } + }, + { + language: "fr", + region: "", + script: "", + isRtl: false, + name: "French", + localizedName: "Français", + pluralType: (n) => { return (n===0 || n===1) ? "one" : "other"; } + }, + { + language: "pt", + region: "BR", + script: "", + isRtl: false, + name: "Brazilian Portuguese", + localizedName: "Português (Brasil)", + pluralType: (n) => { return (n>=0 && n<=1) ? "one" : "other"; } + }, + { + language: "ru", + region: "", + script: "", + isRtl: false, + name: "Russian", + localizedName: "Русский", + pluralType: (n) => { return ((n%10===1) && (n%100!==11)) ? "one" : ((n%10>=2 && n%10<=4) && ((n%100<12 || n%100>14))) ? "few" : "many"; } + }, + { + language: "zh", + region: "", + script: "Hans", + isRtl: false, + name: "Simplified Chinese", + localizedName: "简体中文", + pluralType: (n) => { return "other"; } } ], files: [ @@ -22,7 +67,12 @@ const localazyMetadata = { buildType: "", productFlavors: [], cdnFiles: { - "en#": "https://delivery.localazy.com/_a7797965569058078203416ae5aa/_e0/54b977214afbffe2ffeb07d0ccb03558e75e4408/en/file.json" + "de#": "https://delivery.localazy.com/_a7797965569058078203416ae5aa/_e0/54b977214afbffe2ffeb07d0ccb03558e75e4408/de/file.json", + "en#": "https://delivery.localazy.com/_a7797965569058078203416ae5aa/_e0/54b977214afbffe2ffeb07d0ccb03558e75e4408/en/file.json", + "fr#": "https://delivery.localazy.com/_a7797965569058078203416ae5aa/_e0/54b977214afbffe2ffeb07d0ccb03558e75e4408/fr/file.json", + "pt_BR#": "https://delivery.localazy.com/_a7797965569058078203416ae5aa/_e0/54b977214afbffe2ffeb07d0ccb03558e75e4408/pt-BR/file.json", + "ru#": "https://delivery.localazy.com/_a7797965569058078203416ae5aa/_e0/54b977214afbffe2ffeb07d0ccb03558e75e4408/ru/file.json", + "zh#Hans": "https://delivery.localazy.com/_a7797965569058078203416ae5aa/_e0/54b977214afbffe2ffeb07d0ccb03558e75e4408/zh-Hans/file.json" } } ] diff --git a/server/models/locales.mjs b/server/models/locales.mjs index a76e4a5e..6232b41f 100644 --- a/server/models/locales.mjs +++ b/server/models/locales.mjs @@ -47,6 +47,7 @@ export class Locale extends Model { const dbLocales = await WIKI.db.locales.query().select('code', 'updatedAt') + let localFilesSkipped = 0 for (const lang of localesMeta.languages) { // -> Build filename const langFilenameParts = [lang.language] @@ -63,27 +64,35 @@ export class Locale extends Model { // -> Get File version const flPath = path.join(WIKI.SERVERPATH, `locales/${langFilename}.json`) - const flStat = await stat(flPath) - const flUpdatedAt = DateTime.fromJSDate(flStat.mtime) + try { + const flStat = await stat(flPath) + const flUpdatedAt = DateTime.fromJSDate(flStat.mtime) - // -> Load strings - if (!dbLang || DateTime.fromJSDate(dbLang.updatedAt) < flUpdatedAt || force) { - WIKI.logger.debug(`Loading locale ${langFilename} into DB...`) - const flStrings = JSON.parse(await readFile(flPath, 'utf8')) - await WIKI.db.locales.query().insert({ - code: langFilename, - name: lang.name, - nativeName: lang.localizedName, - language: lang.language, - region: lang.region, - script: lang.script, - isRTL: lang.isRtl, - strings: flStrings - }).onConflict('code').merge(['strings', 'updatedAt']) - } else { - WIKI.logger.debug(`Locale ${langFilename} is newer in the DB. Skipping disk version.`) + // -> Load strings + if (!dbLang || DateTime.fromJSDate(dbLang.updatedAt) < flUpdatedAt || force) { + WIKI.logger.debug(`Loading locale ${langFilename} into DB...`) + const flStrings = JSON.parse(await readFile(flPath, 'utf8')) + await WIKI.db.locales.query().insert({ + code: langFilename, + name: lang.name, + nativeName: lang.localizedName, + language: lang.language, + region: lang.region, + script: lang.script, + isRTL: lang.isRtl, + strings: flStrings + }).onConflict('code').merge(['strings', 'updatedAt']) + } else { + WIKI.logger.debug(`Locale ${langFilename} is newer in the DB. Skipping disk version. [ OK ]`) + } + } catch (err) { + localFilesSkipped++ + WIKI.logger.debug(`Locale ${langFilename} not found on disk. Missing strings file. [ SKIPPED ]`) } } + if (localFilesSkipped > 0) { + WIKI.logger.info(`${localFilesSkipped} locales were defined in the metadata file but not found on disk. [ SKIPPED ]`) + } } catch (err) { WIKI.logger.warn(`Failed to load locales from disk: [ FAILED ]`) WIKI.logger.warn(err)