Jesway / flutter_translate

Flutter Translate is a fully featured localization / internationalization (i18n) library for Flutter.
MIT License
403 stars 118 forks source link

Use fallback locale in case a key is missing for the current one #34

Closed neokree closed 4 years ago

neokree commented 4 years ago

Hi,

I would like to be able to set a "fallback" language for missing keys (not missing locales).

For example, having this situation:

en.json

{
"language": "English"
}

it.json

{
}

main.dart

delegate = await LocalizationDelegate.create(
fallbackLocale: 'en',
supportedLocales: ['it', 'en']);

When I open my app with the IT locale, I would like to see English when I call translate('language')

Let me know if my request is feasible and clear. Thanks

bratan commented 4 years ago

@neokree - Hi, the request is clear but I will not be implementing this behavior since generally there shouldn't be any missing keys.

If you can point out a specific scenario where this behavior would make sense I could reconsider.

neokree commented 4 years ago

Hi @bratan I understand your position, but I think that this feature could be useful for apps that need to go in production but not with all translation, for example when there is a deadline but translators did not finish and the company wants to deploy anyway.

In those cases with the current approach we must go manually to set the missing keys to another language, which will then becomes a problem when the translated text must be replaced because there is not a clear way to know if the developers replaced all "fallback" translations into the new localized ones.

With my proposed one in the same situation we could add a "fallback" flag and deploy anyway, and when the translator finished add all keys knowing that if we missed any translation we can use tools like json-diff to find them.

I agree with you that this situation should not happen often (I just set up a CI job to check for missing translations in my project), but It would be useful in some cases

doc-rj commented 3 years ago

Hi @bratan I agree with @neokree. This is also the way native Android apps work. There is a default/fallback language (in our case it's English) for when a key is missing. This has been quite valuable for our app. Most users know English as a second language (if not first) and we support multiple languages. Sometimes, however, we cannot get all translations in time for first release of a feature. And, it is better to show the English translation than to show the name of the key (which is not intended for display).

HugoHeneault commented 1 year ago

Agreed with @neokree and @doc-rj.

I created a small script to sync translations when needed (this one sync fr file with the others but you could change it) :


import fs from 'fs';
import path from 'path';

import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

function syncJson(src, target) {
  // Ajouter les clés de fr à target
  for (let key in src) {
      if (typeof src[key] === 'object' && src[key] !== null) {
        if (!target.hasOwnProperty(key) || typeof target[key] !== 'object') {
          target[key] = {};
        }
        syncJson(src[key], target[key]);
      } else if (!target.hasOwnProperty(key)) {
        target[key] = src[key];
      }
    }

    // Supprimer les clés de trad qui n'existent pas dans fr
    for (let key in target) {
      if (!src.hasOwnProperty(key)) {
        delete target[key];
      } else if (typeof target[key] === 'object' && target[key] !== null) {
        syncJson(src[key], target[key]);
      }
    }
}

const frPath = path.join(__dirname, '../assets/i18n/fr.json');
let frJson = JSON.parse(fs.readFileSync(frPath, 'utf8'));
fs.writeFileSync(frPath, JSON.stringify(frJson, Object.keys(frJson).sort(), 2), 'utf8');

let langFiles = ['it', 'es', 'ca', 'en']; // ajoutez d'autres langues si nécessaire

for (let langFile of langFiles) {
  let targetPath = path.join(__dirname, `../assets/i18n/${langFile}.json`);

  let targetJson = fs.existsSync(targetPath) ? JSON.parse(fs.readFileSync(targetPath, 'utf8')) : {};

  // synchroniser les fichiers
  syncJson(frJson, targetJson);

  // écrire le fichier de langue synchronisé
  fs.writeFileSync(targetPath, JSON.stringify(targetJson, Object.keys(targetJson).sort(), 2), 'utf8');
}
rignaneseleo commented 9 months ago

I can also add that some values, like the languages themselves or the branding, might be untranslatable. So all of these strings can stay in the en.json file (or whatever is the default one) and the library should read them if not found in the other jsons.