From 9c600d039631143d131857406569a1cc963106d8 Mon Sep 17 00:00:00 2001 From: axolotle Date: Sat, 18 Nov 2023 14:36:55 +0100 Subject: [PATCH] i18n: add per locale specific fallback that can be setup by translators --- i18n.config.ts | 12 +- locales/br.json | 1 + locales/en.json | 1 + maintenance/clean_locales.py | 11 +- maintenance/locales.json | 568 ++++++++++++++++++----------------- 5 files changed, 307 insertions(+), 286 deletions(-) diff --git a/i18n.config.ts b/i18n.config.ts index dc2edeb..2f343a0 100644 --- a/i18n.config.ts +++ b/i18n.config.ts @@ -1,4 +1,14 @@ +import locales from './maintenance/locales.json' + +// https://vue-i18n.intlify.dev/guide/essentials/fallback#explicit-fallback-with-decision-maps +const fallbackLocale = Object.fromEntries( + locales + .filter((locale) => locale.fallback) + .map((locale) => [locale.code, locale.fallback]), +) as Record +fallbackLocale.default = ['en'] + export default defineI18nConfig(() => ({ legacy: false, - fallbackLocale: 'en', + fallbackLocale, })) diff --git a/locales/br.json b/locales/br.json index c4b33d5..3fa56fb 100644 --- a/locales/br.json +++ b/locales/br.json @@ -2,6 +2,7 @@ "_language": { "code": "br", "dir": "ltr", + "fallback": "fr", "name": "Brezhoneg" } } diff --git a/locales/en.json b/locales/en.json index 8e4752f..a6c8dbc 100644 --- a/locales/en.json +++ b/locales/en.json @@ -2,6 +2,7 @@ "_language": { "code": "en", "dir": "ltr", + "fallback": "en", "name": "English" }, "add_forward": "Add an e-mail forwarding address", diff --git a/maintenance/clean_locales.py b/maintenance/clean_locales.py index 9d105db..861a65b 100644 --- a/maintenance/clean_locales.py +++ b/maintenance/clean_locales.py @@ -78,23 +78,30 @@ def remove_stale_translations(ref="en", locales=None): def generate_locales_list(): locales = [] - for locale in ALL_LOCALES: + for locale in sorted(ALL_LOCALES): path = LOCALE_FILES[locale] data = get_json(path).get("_language", {}) code = data.get("code", locale) + fallback = [ + code.strip() for code in data.get("fallback", "").strip().split(",") + ] + # Remove "en" from fallback locales since there's already a last resort fallback to "en" + fallback = [code for code in fallback if code not in ("en", "")] + if locale != code: # Warn that translators have changed the language code print( f"Language's code for file '{locale}.json' is '{code}': file" " should probably be renamed to '{code}.json'" ) + locales.append( { "code": code, "iso": code, "name": data.get("name", code), "dir": data.get("dir", "ltr"), - "fallback": data.get("fallback", "en"), + "fallback": fallback or None, "file": f"{locale}.json", } ) diff --git a/maintenance/locales.json b/maintenance/locales.json index ba4e7ce..f15006f 100644 --- a/maintenance/locales.json +++ b/maintenance/locales.json @@ -1,330 +1,332 @@ [ - { - "code": "el", - "dir": "ltr", - "fallback": "en", - "file": "el.json", - "iso": "el", - "name": "Eλληνικά" - }, - { - "code": "te", - "dir": "ltr", - "fallback": "en", - "file": "te.json", - "iso": "te", - "name": "Telugu" - }, - { - "code": "ja", - "dir": "ltr", - "fallback": "en", - "file": "ja.json", - "iso": "ja", - "name": "日本語" - }, { "code": "ar", "dir": "rtl", - "fallback": "en", + "fallback": null, "file": "ar.json", "iso": "ar", "name": "العربية" }, - { - "code": "fi", - "dir": "ltr", - "fallback": "en", - "file": "fi.json", - "iso": "fi", - "name": "Suomi" - }, - { - "code": "ne", - "dir": "ltr", - "fallback": "en", - "file": "ne.json", - "iso": "ne", - "name": "नेपाली" - }, - { - "code": "de", - "dir": "ltr", - "fallback": "en", - "file": "de.json", - "iso": "de", - "name": "Deutsch" - }, - { - "code": "es", - "dir": "ltr", - "fallback": "en", - "file": "es.json", - "iso": "es", - "name": "Español" - }, - { - "code": "it", - "dir": "ltr", - "fallback": "en", - "file": "it.json", - "iso": "it", - "name": "Italiano" - }, - { - "code": "pl", - "dir": "ltr", - "fallback": "en", - "file": "pl.json", - "iso": "pl", - "name": "Polski" - }, - { - "code": "uk", - "dir": "ltr", - "fallback": "en", - "file": "uk.json", - "iso": "uk", - "name": "Українська" - }, - { - "code": "eo", - "dir": "ltr", - "fallback": "en", - "file": "eo.json", - "iso": "eo", - "name": "Esperanto" - }, - { - "code": "he", - "dir": "rtl", - "fallback": "en", - "file": "he.json", - "iso": "he", - "name": "עברית" - }, - { - "code": "id", - "dir": "ltr", - "fallback": "en", - "file": "id.json", - "iso": "id", - "name": "Bahasa Indonesia" - }, - { - "code": "ca", - "dir": "ltr", - "fallback": "en", - "file": "ca.json", - "iso": "ca", - "name": "Català" - }, - { - "code": "en", - "dir": "ltr", - "fallback": "en", - "file": "en.json", - "iso": "en", - "name": "English" - }, - { - "code": "lt", - "dir": "ltr", - "fallback": "en", - "file": "lt.json", - "iso": "lt", - "name": "Lietuvių" - }, - { - "code": "kab", - "dir": "ltr", - "fallback": "en", - "file": "kab.json", - "iso": "kab", - "name": "Taqbaylit" - }, - { - "code": "hu", - "dir": "ltr", - "fallback": "en", - "file": "hu.json", - "iso": "hu", - "name": "Magyar" - }, - { - "code": "eu", - "dir": "ltr", - "fallback": "en", - "file": "eu.json", - "iso": "eu", - "name": "Euskara" - }, - { - "code": "cs", - "dir": "ltr", - "fallback": "en", - "file": "cs.json", - "iso": "cs", - "name": "Čeština" - }, - { - "code": "sv", - "dir": "ltr", - "fallback": "en", - "file": "sv.json", - "iso": "sv", - "name": "Svenska" - }, - { - "code": "oc", - "dir": "ltr", - "fallback": "en", - "file": "oc.json", - "iso": "oc", - "name": "Occitan" - }, - { - "code": "ru", - "dir": "ltr", - "fallback": "en", - "file": "ru.json", - "iso": "ru", - "name": "Русский" - }, - { - "code": "sl", - "dir": "ltr", - "fallback": "en", - "file": "sl.json", - "iso": "sl", - "name": "Slovenščina" - }, - { - "code": "br", - "dir": "ltr", - "fallback": "en", - "file": "br.json", - "iso": "br", - "name": "Brezhoneg" - }, - { - "code": "nb-NO", - "dir": "ltr", - "fallback": "en", - "file": "nb_NO.json", - "iso": "nb-NO", - "name": "Norsk bokmål" - }, - { - "code": "pt", - "dir": "ltr", - "fallback": "en", - "file": "pt.json", - "iso": "pt", - "name": "Português" - }, - { - "code": "mk", - "dir": "ltr", - "fallback": "en", - "file": "mk.json", - "iso": "mk", - "name": "македонски" - }, - { - "code": "fr", - "dir": "ltr", - "fallback": "en", - "file": "fr.json", - "iso": "fr", - "name": "Français" - }, - { - "code": "nl", - "dir": "ltr", - "fallback": "en", - "file": "nl.json", - "iso": "nl", - "name": "Nederlands" - }, - { - "code": "fa", - "dir": "rtl", - "fallback": "en", - "file": "fa.json", - "iso": "fa", - "name": "فارسی" - }, - { - "code": "hi", - "dir": "ltr", - "fallback": "en", - "file": "hi.json", - "iso": "hi", - "name": "हिन्दी" - }, - { - "code": "tr", - "dir": "ltr", - "fallback": "en", - "file": "tr.json", - "iso": "tr", - "name": "Türkçe" - }, - { - "code": "pt-BR", - "dir": "ltr", - "fallback": "en", - "file": "pt_BR.json", - "iso": "pt-BR", - "name": "Português brasileiro" - }, { "code": "bn-BD", "dir": "ltr", - "fallback": "en", + "fallback": null, "file": "bn_BD.json", "iso": "bn-BD", "name": "বাংলা" }, + { + "code": "br", + "dir": "ltr", + "fallback": [ + "fr" + ], + "file": "br.json", + "iso": "br", + "name": "Brezhoneg" + }, + { + "code": "ca", + "dir": "ltr", + "fallback": null, + "file": "ca.json", + "iso": "ca", + "name": "Català" + }, { "code": "ckb", "dir": "rtl", - "fallback": "en", + "fallback": null, "file": "ckb.json", "iso": "ckb", "name": "کوردی" }, { - "code": "zh_Hans", + "code": "cs", "dir": "ltr", - "fallback": "en", - "file": "zh_Hans.json", - "iso": "zh_Hans", - "name": "简化字" + "fallback": null, + "file": "cs.json", + "iso": "cs", + "name": "Čeština" }, { "code": "da", "dir": "ltr", - "fallback": "en", + "fallback": null, "file": "da.json", "iso": "da", "name": "Dansk" }, + { + "code": "de", + "dir": "ltr", + "fallback": null, + "file": "de.json", + "iso": "de", + "name": "Deutsch" + }, + { + "code": "el", + "dir": "ltr", + "fallback": null, + "file": "el.json", + "iso": "el", + "name": "Eλληνικά" + }, + { + "code": "en", + "dir": "ltr", + "fallback": null, + "file": "en.json", + "iso": "en", + "name": "English" + }, + { + "code": "eo", + "dir": "ltr", + "fallback": null, + "file": "eo.json", + "iso": "eo", + "name": "Esperanto" + }, + { + "code": "es", + "dir": "ltr", + "fallback": null, + "file": "es.json", + "iso": "es", + "name": "Español" + }, + { + "code": "eu", + "dir": "ltr", + "fallback": null, + "file": "eu.json", + "iso": "eu", + "name": "Euskara" + }, + { + "code": "fa", + "dir": "rtl", + "fallback": null, + "file": "fa.json", + "iso": "fa", + "name": "فارسی" + }, + { + "code": "fi", + "dir": "ltr", + "fallback": null, + "file": "fi.json", + "iso": "fi", + "name": "Suomi" + }, + { + "code": "fr", + "dir": "ltr", + "fallback": null, + "file": "fr.json", + "iso": "fr", + "name": "Français" + }, { "code": "gl", "dir": "ltr", - "fallback": "en", + "fallback": null, "file": "gl.json", "iso": "gl", "name": "Galego" }, + { + "code": "he", + "dir": "rtl", + "fallback": null, + "file": "he.json", + "iso": "he", + "name": "עברית" + }, + { + "code": "hi", + "dir": "ltr", + "fallback": null, + "file": "hi.json", + "iso": "hi", + "name": "हिन्दी" + }, + { + "code": "hu", + "dir": "ltr", + "fallback": null, + "file": "hu.json", + "iso": "hu", + "name": "Magyar" + }, + { + "code": "id", + "dir": "ltr", + "fallback": null, + "file": "id.json", + "iso": "id", + "name": "Bahasa Indonesia" + }, + { + "code": "it", + "dir": "ltr", + "fallback": null, + "file": "it.json", + "iso": "it", + "name": "Italiano" + }, + { + "code": "ja", + "dir": "ltr", + "fallback": null, + "file": "ja.json", + "iso": "ja", + "name": "日本語" + }, + { + "code": "kab", + "dir": "ltr", + "fallback": null, + "file": "kab.json", + "iso": "kab", + "name": "Taqbaylit" + }, + { + "code": "lt", + "dir": "ltr", + "fallback": null, + "file": "lt.json", + "iso": "lt", + "name": "Lietuvių" + }, + { + "code": "mk", + "dir": "ltr", + "fallback": null, + "file": "mk.json", + "iso": "mk", + "name": "македонски" + }, + { + "code": "nb-NO", + "dir": "ltr", + "fallback": null, + "file": "nb_NO.json", + "iso": "nb-NO", + "name": "Norsk bokmål" + }, + { + "code": "ne", + "dir": "ltr", + "fallback": null, + "file": "ne.json", + "iso": "ne", + "name": "नेपाली" + }, + { + "code": "nl", + "dir": "ltr", + "fallback": null, + "file": "nl.json", + "iso": "nl", + "name": "Nederlands" + }, + { + "code": "oc", + "dir": "ltr", + "fallback": null, + "file": "oc.json", + "iso": "oc", + "name": "Occitan" + }, + { + "code": "pl", + "dir": "ltr", + "fallback": null, + "file": "pl.json", + "iso": "pl", + "name": "Polski" + }, + { + "code": "pt", + "dir": "ltr", + "fallback": null, + "file": "pt.json", + "iso": "pt", + "name": "Português" + }, + { + "code": "pt-BR", + "dir": "ltr", + "fallback": null, + "file": "pt_BR.json", + "iso": "pt-BR", + "name": "Português brasileiro" + }, + { + "code": "ru", + "dir": "ltr", + "fallback": null, + "file": "ru.json", + "iso": "ru", + "name": "Русский" + }, { "code": "sk", "dir": "ltr", - "fallback": "en", + "fallback": null, "file": "sk.json", "iso": "sk", "name": "Slovak" + }, + { + "code": "sl", + "dir": "ltr", + "fallback": null, + "file": "sl.json", + "iso": "sl", + "name": "Slovenščina" + }, + { + "code": "sv", + "dir": "ltr", + "fallback": null, + "file": "sv.json", + "iso": "sv", + "name": "Svenska" + }, + { + "code": "te", + "dir": "ltr", + "fallback": null, + "file": "te.json", + "iso": "te", + "name": "Telugu" + }, + { + "code": "tr", + "dir": "ltr", + "fallback": null, + "file": "tr.json", + "iso": "tr", + "name": "Türkçe" + }, + { + "code": "uk", + "dir": "ltr", + "fallback": null, + "file": "uk.json", + "iso": "uk", + "name": "Українська" + }, + { + "code": "zh_Hans", + "dir": "ltr", + "fallback": null, + "file": "zh_Hans.json", + "iso": "zh_Hans", + "name": "简化字" } ]