#json #flutter #dart #localization
Вопрос:
Мы используем flutter easy localizations
и у нас есть тексты, в которых используются аргументы. Так, например, у нас есть строка в нашем localizations
документе, как показано ниже,
{ "someAppText":"This is {} app text {}." }
Но иногда аргумент будет пустым. Что приведет к следующему тексту
This is[SPACE][SPACE]app text[SPACE].
Где места все еще есть. Можно ли сделать отступ всякий раз, когда у нас нет аргументов?
Комментарии:
1. Решает ли мой ответ ваш вопрос?
Ответ №1:
Во-первых, как насчет использования plural
? Похоже, вы хотите иметь другой текст для разных типов данных. Я не привожу других примеров, когда аргумент будет пустым, поэтому, если это не ваш случай, не могли бы вы привести конкретный пример?
Во-вторых, вы можете выполнить простую манипуляцию со строками следующим образом (псевдокод). Код демонстрирует только самый простой случай (чтобы сделать его кратким), но его тривиально распространить на полный случай.
String myTranslate(String formatString, Listlt;Stringgt; args) { const EMPTY_MARKER = 'EMPTY_MARKER'; final transformedArgs = args.map((arg) =gt; arg.isEmpty ? EMPTY_MARKER : arg).toList(); final rawString = formatString.tr(transformedArgs); return rawString.replaceAll(' $EMPTY_MARKER', ''); }
Затем в вашем примере он выведет: This is[SPACE]app text.
Ответ №2:
мы не можем добавлять какие-либо методы в файл JSON, а должны использовать только его простые данные maplt;Строка, строкаgt;
так
обходное решение будет использовать специальные строки внутри JSON, чтобы иметь возможность обнаруживать и обрабатывать их во время выполнения
допустим, у JSON будет это
{ "someAppText": "This is #VAR01 app text #VAR02." }
затем давайте создадим другой класс, у которого есть методы для обработки этих специальных слов, они должны их обнаруживать и заменять другими динамическими входными данными
так
class JSONWorkAround { /// A - need to define the string pattern we are using in the string which I assumed to look like '#VAR00' /// let's call them jsonVariables /// NOTE : if you would like to name them #VAR000 ,, then regExp would be r'#VAR...' static RegExp regExp = RegExp(r'#VAR..'); /// B - let's make a tracker for any word that matches this regExp in any input string static Listlt;Stringgt; _searchJSONVariablesByRegExp({@required String text, @required RegExp regExp}){ Listlt;Stringgt; _strings; /// always check if not null before we do stuff to avoid errors and save performance if (text != null){ _strings = regExp.allMatches(text).map((m) =gt; m.group(0)).toList(); } return _strings; } /// C - let's make the tracker specifically for those JSONVariables from a string received from the JSON doc "let's call it rawString" static Listlt;Stringgt; _searchJSONVariablesFromRawString({@required String rawString}){ final Listlt;Stringgt; _jsonVariables = _searchJSONVariablesByRegExp(text: rawString, regExp: regExp); return _jsonVariables; } /// E - let's see what to do with the search result static Listlt;SpecialWordgt; _processJSONVariables(Listlt;Stringgt; jsonVariables){ Listlt;SpecialWordgt; _outputSpecialWords = lt;SpecialWordgt;[]; /// so w notice we will need to process each one alone,, so we loop them out if(jsonVariables != null amp;amp; jsonVariables.isNotEmpty){ jsonVariables.forEach((jsonVariable) { /// we should receive a substitute string instead of that #VAR00 special string,, so .. /// actually we need to receive a string that is accompanied with its cipher special thing to be able to go back to the sentence and change it,,, like using this special #VAR00 thing as ID /// and I don't like maplt;String, dynamicgt; but I would rather create a model class ,, will be written down there at the end of this class final SpecialWord _substitute = _processSingleJSONVariable(jsonVariable: jsonVariable); /// then we add them to the output List if (_substitute != null){ _outputSpecialWords.add(_substitute); } }); } return _outputSpecialWords; } /// D - need to receive both the substitute and its (JSONSpecialVariable / ID) to be able to search for it and process it in the original string static SpecialWord _processSingleJSONVariable({@required String jsonVariable}){ final SpecialWord _substitute = SpecialWord.getSpecialWordFromAllSpecialWordsByID(jsonVariable); return _substitute; } /// F - finally after receiving the substitutes inside a listlt;SpecialWordgt;,, we get get back the original String with the substitutes static String processJSONStringThatContainsThoseSpecialVariables(String rawString){ /// this has to initialize with the initial raw string value to be processed String _processedString = rawString; final Listlt;Stringgt; _jsonVariables = _searchJSONVariablesFromRawString(rawString: rawString); if (_jsonVariables != null amp;amp; _jsonVariables.isNotEmpty){ final Listlt;SpecialWordgt; _specialWords = _processJSONVariables(_jsonVariables); /// then we need to change each jsonVariable with its substitute _specialWords.forEach((specialWord) { _processedString = _replaceSubStringWith( subStringToReplace: specialWord.id, replacement: specialWord.substitute, input: _processedString, ); }); } return _processedString; } /// G - a text replacing method to easily replace a given subString from a string with another value static String _replaceSubStringWith({@required String subStringToReplace, @required String replacement, @required String input}){ final String _output = input.replaceAll(subStringToReplace, replacement); return _output; } } class SpecialWord{ final String id; final String substitute; // you can change this to be more complex to adapt to many languages or other things const SpecialWord({ @required this.id, @required this.substitute, }); /// lets create a list of constants that u may change in future and call from db or wherever static const Listlt;SpecialWordgt; _allSpecialWords = const lt;SpecialWordgt;[ SpecialWord(id: '#VAR01', substitute: 'Baby'), SpecialWord(id: '#VAR02', substitute: 'Cool'), SpecialWord(id: '#VAR03', substitute: 'You got the Idea'), ]; /// I like to pamper myself with super quick methods to be clean and organized static SpecialWord getSpecialWordFromAllSpecialWordsByID(String id){ SpecialWord _foundWord; if (id != null){ _foundWord = _allSpecialWords.firstWhere((word) =gt; word.id == id, orElse: () =gt; null); } return _foundWord; } }
затем давайте проведем небольшой тест метода, чтобы убедиться в безопасности этой котельной плиты по разработанному коду
test("Testing JSON Variables work around idea", () async { String _rawString = "This is #VAR01 app text #VAR02."; String _processedString = JSONWorkAround.processJSONStringThatContainsThoseSpecialVariables(_rawString); String _expectation = "This is Baby app text Cool."; expect(_processedString, _expectation); });
Но теперь вы можете спросить себя, стоит ли это того, я все продумал, есть ли более мудрое решение?,, может быть, просто сохраните каждый случай в json с самого начала,, я не знаю,,
Боюсь, я слишком усложнил решение, но оно работает как заклинание
Ответ №3:
Я не уверен, что понял вашу проблему. Но попробуйте сделать следующее.
Добавьте два перевода один для пустого аргумента someAppTextEmpty
и один для обычного someAppText
{ "someAppText": "This is {} app text {}.", "someAppTextEmpty": "This is the alternative app text." }
Затем проверьте, является ли аргумент пустым или нет, чтобы получить правильный ключ перевода:
final String translationKey = argument.isNotEmpty ? 'someAppText' : 'someAppTextEmpty';
Затем передайте переменную translationKey
в функцию перевода easy_localization
примерно так:
final String title = tr(translationKey); // Or Text(translationKey).tr(); // Or translationKey.tr();
Ответ №4:
Нет.
С помощью easy_localization или без нее символ обратного пробела в Dart занимает 1 пробел в строке вместо удаления 1 пробела. Таков мой вывод методом проб и ошибок.
Мое предложение:
- Создайте строку под названием BACKSPACE с никогда не используемым значением, начинающимся с пробела, например:
final String BACKSPACE = 'NEVER_USED_VALUE';
- При необходимости назначьте BACKSPACE значениям 1 и 2 вместо пустой строки.
- Затем сделайте это:
'someAppText'.tr(value1, value2).replaceAll(' ' BACKSPACE, '');