Можно ли заменить {} пробелом для локализации

#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 пробела. Таков мой вывод методом проб и ошибок.

Мое предложение:

  1. Создайте строку под названием BACKSPACE с никогда не используемым значением, начинающимся с пробела, например:
     final String BACKSPACE = 'NEVER_USED_VALUE';  
  2. При необходимости назначьте BACKSPACE значениям 1 и 2 вместо пустой строки.
  3. Затем сделайте это:
     'someAppText'.tr(value1, value2).replaceAll(' '   BACKSPACE, '');