Skip to content

i18n Code Style

В данной статье описаны как надо и как не надо менять файлы .i18n.json

Формат ключей

Ключи называем в snake_case

TIP

При генерации кода, генерируются геттеры в snake_case и потом невозможно найти источник локализации поиском по геттеру, потому что в json ключи хранятся в другом формате

json
// [!code class:bad]
"profileWidget": {
  "sammaVodkaStart": "To start, begin",
  "sammaVodkaPrefix": "Sammagonka  ",
  "sammaVodkaContinuePostfix": "'.\nKeep going!",
}
json
// [!code class:good]
"profile_widget": {
  "samma_vodka_start": "To start, begin",
  "samma_vodka_prefix": "Sammagonka  ",
  "samma_vodka_continue_postfix": "'.\nKeep going!",
}

**_text в ключах

Старайся избегать _text в ключах. Ты и так используешь инструмент для текстов, это понятно из контекста

json
// [!code class:bad]
"profile_widget": {
  "samma_vodka_start_text": "To start, begin"
}
json
// [!code class:good]
"profile_widget": {
  "samma_vodka_start": "To start, begin"
}

Можно использовать одинарный ключ "text", если ничего больше не подходит по смыслу

json
// [!code class:good]
"profile_widget": {
  "text": {
    "no_progress": "...",
    "has_progress": "..."
  }
}

Составной текст

Старайся использовать только один ключ в коде для одного кейса вместо составных текстов

json
// [!code class:bad]
"profile": {
  "samma_vodka_start": "Для начала  начни",
  "samma_vodka_prefix": "Саммагонка  $duration",
  "samma_vodka_continue_postfix": "'.\nKeep going!",
}
dart
// [!code class:bad]
final isActive = progress != 0 && progress != 1;
final duration = durationRaw.let((it) => DateTimeUtils.formatDuration(context, it));

final result = durationRaw == null || durationRaw == 0
  ? context.t.knowledge_sprint.profile_widget.samma_vodka_start_text
  : context.t.knowledge_sprint.profile_widget.samma_vodka_prefix +
    duration +
    (isActive ? context.t.knowledge_sprint.profile_widget.samma_vodka_continue_postfix : '');

return Text(result)
json
// [!code class:good]
"profile": {
  "text": {
    "no_progress": "Для начала  начни",
    "has_progress": "Саммагонка  $duration",
    "active": "@:knowledge_sprint.profile.text.has_progress.\nПродолжай!"
  }
}
dart
// [!code class:good]
final isActive = progress != 0 && progress != 1;
final duration = durationRaw.let((it) => DateTimeUtils.formatDuration(context, it));

final String text;
if (durationRaw == null || durationRaw == 0) {
  text = context.t.knowledge_sprint.profile_widget.text.no_progress;
} else if (isActive) {
  text = context.t.knowledge_sprint.profile_widget.text.active(duration: duration!);
} else {
  text = context.t.knowledge_sprint.profile_widget.text.has_progress(duration: duration!);
}

return Text(text);

Понятный нейминг

Используй понятный и легкочитаемый нейминг. Старайся избегать двойного отрицания

json
// [!code class:bad]
"bottom_sheet": {
  "empty_result": {
    "title": "Опа, $name не в саммагонке!"
  },
  "not_empty_result": {
    "title": "$name бьет рекорды:\n $days подряд!"
  }
}
json
// [!code class:good]
"bottom_sheet": {
  "no_results": {
    "title": "Опа, $name не в саммагонке!"
  },
  "has_results": {
    "title": "$name бьет рекорды:\n $days подряд!"
  }
}

Авторы

The avatar of contributor named as melvspace melvspace
The avatar of contributor named as Vadim Melnikov Vadim Melnikov

История