[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-8028":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":22,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":29,"readmeContent":30,"aiSummary":31,"trendingCount":16,"starSnapshotCount":16,"syncStatus":17,"lastSyncTime":32,"discoverSource":33},8028,"i18n-tasks","glebm\u002Fi18n-tasks","glebm","Manage translation and localization with static analysis, for Ruby i18n","http:\u002F\u002Fglebm.github.io\u002Fi18n-tasks",null,"Ruby",2160,285,31,50,0,2,29.37,"MIT License",false,"main",true,[24,25,26,27,28],"i18n","ruby","static-analysis","static-code-analysis","translation-management","2026-06-12 02:01:47","# i18n-tasks [![Build Status][badge-ci]][ci] [![Coverage Status][badge-coverage]][coverage] [![Gitter](https:\u002F\u002Fbadges.gitter.im\u002FJoin%20Chat.svg)](https:\u002F\u002Fgitter.im\u002Fglebm\u002Fi18n-tasks?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n[![Stand With Ukraine](https:\u002F\u002Fraw.githubusercontent.com\u002Fvshymanskyy\u002FStandWithUkraine\u002Fmain\u002Fbanner2-direct.svg)](https:\u002F\u002Fstand-with-ukraine.pp.ua\u002F)\n\ni18n-tasks helps you find and manage missing and unused translations.\n\n\u003Cimg width=\"539\" height=\"331\" src=\"https:\u002F\u002Fi.imgur.com\u002FXZBd8l7.png\">\n\nThis gem analyses code statically for key usages, such as `I18n.t('some.key')`, in order to:\n\n- Report keys that are missing or unused.\n- Pre-fill missing keys, optionally from Google Translate or DeepL (Pro or Free).\n- Remove unused keys.\n\nThus addressing the two main problems of [i18n gem][i18n-gem] design:\n\n- Missing keys only blow up at runtime.\n- Keys no longer in use may accumulate and introduce overhead, without you knowing it.\n\n## Table of Contents\n\n- [Quick Start](#quick-start)\n- [Commands](#commands)\n  - [Check health](#check-health)\n  - [Find usages](#find-usages)\n  - [Add missing keys](#add-missing-keys)\n  - [Translate missing keys](#translate-missing-keys)\n  - [Remove unused keys](#remove-unused-keys)\n  - [Prune](#prune)\n  - [Normalize](#normalize)\n  - [Move \u002F rename \u002F merge keys](#move--rename--merge-keys)\n  - [Delete keys](#delete-keys)\n  - [Compose tasks](#compose-tasks)\n- [Configuration](#configuration)\n  - [Locales](#locales)\n  - [Storage & locale files](#storage--locale-files)\n    - [Pattern router](#pattern-router)\n    - [Conservative router](#conservative-router)\n    - [Isolating router](#isolating-router)\n    - [Key pattern syntax](#key-pattern-syntax)\n    - [Custom adapters](#custom-adapters)\n    - [Rails credentials](#rails-credentials)\n  - [Usage search](#usage-search)\n    - [Prism-based scanner](#prism-based-scanner)\n  - [Fine-tuning](#fine-tuning)\n  - [Environment variables & dotenv](#environment-variables--dotenv)\n- [Translation backends](#translation-backends)\n  - [Google Translate](#google-translate)\n  - [DeepL](#deepl)\n  - [Yandex](#yandex)\n  - [OpenAI](#openai)\n  - [watsonx](#watsonx)\n- [Features & limitations](#features--limitations)\n  - [Relative keys](#relative-keys)\n  - [Plural keys](#plural-keys)\n  - [Reference keys](#reference-keys)\n  - [Dynamic keys](#dynamic-keys)\n  - [I18n.localize](#i18nlocalize)\n  - [`t()` keyword arguments](#t-keyword-arguments)\n  - [Unexpected normalization](#unexpected-normalization)\n- [Advanced](#advanced)\n  - [Interactive console](#interactive-console)\n  - [CSV import \u002F export](#csv-import--export)\n  - [Add custom tasks](#add-custom-tasks)\n- [Development](#development)\n\n## Quick Start\n\ni18n-tasks can be used with any project using the ruby [i18n gem][i18n-gem] (default in Rails).\n\n1. Add to your `Gemfile`:\n\n   ```ruby\n   gem 'i18n-tasks', '~> 1.1.2', group: :development\n   ```\n\n2. Copy the default [configuration file](#configuration):\n\n   ```sh\n   $ cp $(bundle exec i18n-tasks gem-path)\u002Ftemplates\u002Fconfig\u002Fi18n-tasks.yml config\u002F\n   ```\n\n3. Run your first health check:\n\n   ```sh\n   $ bundle exec i18n-tasks health\n   ```\n\nThat's it. See [Commands](#commands) for the full list of tasks, or [Configuration](#configuration) to tailor the setup to your project.\n\n**Optional:** copy a test that checks for missing\u002Funused translations on every CI run:\n\n```sh\n# RSpec\n$ cp $(bundle exec i18n-tasks gem-path)\u002Ftemplates\u002Frspec\u002Fi18n_spec.rb spec\u002F\n\n# Minitest\n$ cp $(bundle exec i18n-tasks gem-path)\u002Ftemplates\u002Fminitest\u002Fi18n_test.rb test\u002F\n```\n\n## Commands\n\nRun `bundle exec i18n-tasks` to get the list of all the tasks with short descriptions.\n\n### Check health\n\n`bundle exec i18n-tasks health` checks if any keys are missing or not used,\nthat interpolation variables are consistent across locales,\nand that all the locale files are normalized (auto-formatted):\n\n```sh\n$ bundle exec i18n-tasks health\n```\n\n### Find usages\n\nSee where the keys are used with `bundle exec i18n-tasks find`:\n\n```sh\n$ bundle exec i18n-tasks find common.help\n$ bundle exec i18n-tasks find 'auth.*'\n$ bundle exec i18n-tasks find '{number,currency}.format.*'\n```\n\n\u003Cimg width=\"437\" height=\"129\" src=\"https:\u002F\u002Fi.imgur.com\u002FVxBrSfY.png\">\n\n### Add missing keys\n\nAdd missing keys with placeholders (base value or humanized key):\n\n```sh\n$ bundle exec i18n-tasks add-missing\n```\n\nThis and other tasks accept arguments:\n\n```sh\n$ bundle exec i18n-tasks add-missing -v 'TRME %{value}' fr\n```\n\nPass `--help` for more information:\n\n```sh\n$ bundle exec i18n-tasks add-missing --help\nUsage: i18n-tasks add-missing [options] [locale ...]\n    -l, --locales  Comma-separated list of locale(s) to process. Default: all. Special: base.\n    -f, --format   Output format: terminal-table, yaml, json, keys, inspect. Default: terminal-table.\n    -v, --value    Value. Interpolates: %{value}, %{human_key}, %{value_or_human_key}, %{key}. Default: %{value_or_human_key}.\n    -h, --help     Display this help message.\n```\n\n### Translate missing keys\n\nTranslate missing keys using a backend service of your choice.\n\n```sh\n$ bundle exec i18n-tasks translate-missing\n\n# accepts backend, from and locales options\n$ bundle exec i18n-tasks translate-missing --from=base es fr --backend=google\n```\n\nAvailable backends:\n\n- `google` – [Google Translate](#google-translate)\n- `deepl` – [DeepL](#deepl)\n- `yandex` – [Yandex](#yandex)\n- `openai` – [OpenAI](#openai)\n- `watsonx` – [watsonx](#watsonx)\n\n### Remove unused keys\n\n```sh\n$ bundle exec i18n-tasks unused\n$ bundle exec i18n-tasks remove-unused\n```\n\nThese tasks can infer [dynamic keys](#dynamic-keys) such as `t(\"category.\\#{category.name}\")` if you set\n`search.strict` to false, or pass `--no-strict` on the command line.\n\nIf you want to keep the ordering from the original language file when using remove-unused, pass\n`-k` or `--keep-order`.\n\n### Prune keys not in base locale\n\nRemove keys from non-base locales that are absent in the base locale:\n\n```bash\n$ i18n-tasks prune\n```\n\nPass `-k` or `--keep-order` to preserve the original key ordering in the locale files.\n\n### Normalize\n\nSort the keys:\n\n```sh\n$ bundle exec i18n-tasks normalize\n```\n\nSort the keys, and move them to the respective files as defined by [`config.write`](#storage--locale-files):\n\n```sh\n$ bundle exec i18n-tasks normalize -p\n```\n\n### Move \u002F rename \u002F merge keys\n\n`bundle exec i18n-tasks mv \u003Cpattern> \u003Ctarget>` is a versatile task to move or delete keys matching the given pattern.\n\nAll nodes (leafs or subtrees) matching [`\u003Cpattern>`](#key-pattern-syntax) are merged together and moved to `\u003Ctarget>`.\n\nRename a node (leaf or subtree):\n\n```sh\n$ bundle exec i18n-tasks mv user account\n```\n\nMove a node:\n\n```sh\n$ bundle exec i18n-tasks mv user_alerts user.alerts\n```\n\nMove the children one level up:\n\n```sh\n$ bundle exec i18n-tasks mv 'alerts.{:}' '\\1'\n```\n\nMerge-move multiple nodes:\n\n```sh\n$ bundle exec i18n-tasks mv '{user,profile}' account\n```\n\nMerge (non-leaf) nodes into parent:\n\n```sh\n$ bundle exec i18n-tasks mv '{pages}.{a,b}' '\\1'\n```\n\n### Delete keys\n\nDelete the keys by using the `rm` task:\n\n```sh\n$ bundle exec i18n-tasks rm 'user.{old_profile,old_title}' another_key\n```\n\n### Compose tasks\n\n`i18n-tasks` also provides composable tasks for reading, writing and manipulating locale data. Examples below.\n\n`add-missing` implemented with `missing`, `tree-set-value` and `data-merge`:\n\n```sh\n$ bundle exec i18n-tasks missing -f yaml fr | bundle exec i18n-tasks tree-set-value 'TRME %{value}' | bundle exec i18n-tasks data-merge\n```\n\n`remove-unused` implemented with `unused` and `data-remove` (sans the confirmation):\n\n```sh\n$ bundle exec i18n-tasks unused -f yaml | bundle exec i18n-tasks data-remove\n```\n\nRemove all keys from `fr` that do not exist in `en`. Do not change `en`:\n\n```sh\n$ bundle exec i18n-tasks missing -t diff -f yaml en | bundle exec i18n-tasks tree-mv en fr | bundle exec i18n-tasks data-remove\n```\n\nSee the full list of tasks with `bundle exec i18n-tasks --help`.\n\n## Configuration\n\nConfiguration is read from `config\u002Fi18n-tasks.yml` or `config\u002Fi18n-tasks.yml.erb`.\nInspect the configuration with `bundle exec i18n-tasks config`.\n\nInstall the [default config file][config] with:\n\n```sh\n$ cp $(bundle exec i18n-tasks gem-path)\u002Ftemplates\u002Fconfig\u002Fi18n-tasks.yml config\u002F\n```\n\nSettings are compatible with Rails by default.\n\n### Locales\n\nBy default, `base_locale` is set to `en` and `locales` are inferred from the paths to data files.\nYou can override these in the [config][config].\n\n### Storage & locale files\n\nThe default data adapter supports YAML and JSON files.\n\ni18n-tasks can manage multiple translation files and read translations from other gems.\nTo find out more see the `data` options in the [config][config].\nNB: By default, only `%{locale}.yml` files are read, not `namespace.%{locale}.yml`. Make sure to check the config.\n\nFor writing to locale files i18n-tasks provides three routers.\n\n#### Pattern router\n\nPattern router organizes keys based on a list of key patterns, as in the example below:\n\n```yaml\ndata:\n  router: pattern_router\n  # a list of {key pattern => file} routes, matched top to bottom\n  write:\n    # write models.* and views.* keys to the respective files\n    - [\"{models,views}.*\", 'config\u002Flocales\u002F\\1.%{locale}.yml']\n    # or, write every top-level key namespace to its own file\n    - [\"{:}.*\", 'config\u002Flocales\u002F\\1.%{locale}.yml']\n    # default, sugar for ['*', path]\n    - \"config\u002Flocales\u002F%{locale}.yml\"\n```\n\n#### Conservative router\n\nConservative router keeps the keys where they are found, or infers the path from base locale.\nIf the key is completely new, conservative router will fall back to pattern router behaviour.\nConservative router is the **default** router.\n\n```yaml\ndata:\n  router: conservative_router\n  write:\n    - [\"devise.*\", \"config\u002Flocales\u002Fdevise.%{locale}.yml\"]\n    - \"config\u002Flocales\u002F%{locale}.yml\"\n```\n\nIf you want to have i18n-tasks reorganize your existing keys using `data.write`, either set the router to\n`pattern_router` as above, or run `bundle exec i18n-tasks normalize -p` (forcing the use of the pattern router for that run).\n\n#### Isolating router\n\nIsolating router assumes each YAML file is independent and can contain similar keys.\n\nAs a result, the translations are written to an alternate target file for each source file\n(only the `%{locale}` part is changed to match target locale). Thus, it is not necessary to\nspecify any `write` configuration (in fact, it would be completely ignored).\n\nThis can be useful for example when using [ViewComponent sidecars](https:\u002F\u002Fviewcomponent.org\u002Fguide\u002Ftranslations.html)\n(ViewComponent assigns an implicit scope to each sidecar YAML file but `i18n-tasks` is not aware of\nthat logic, resulting in collisions):\n\n- `app\u002Fcomponents\u002Fmovies_component.en.yml`:\n\n  ```yaml\n  en:\n    title: Movies\n  ```\n\n- `app\u002Fcomponents\u002Fgames_component.en.yml`\n  ```yaml\n  en:\n    title: Games\n  ```\n\nThis router has a limitation, though: it does not support detecting missing keys from code usage\n(since it is not aware of the implicit scope logic).\n\n#### Key pattern syntax\n\nA special syntax similar to file glob patterns is used throughout i18n-tasks to match translation keys:\n\n|   syntax   | description                                              |\n| :--------: | :------------------------------------------------------- |\n|    `*`     | matches everything                                       |\n|    `:`     | matches a single key                                     |\n|    `*:`    | matches part of a single key                             |\n| `{a, b.c}` | match any in set, can use `:` and `*`, match is captured |\n\nExample of usage:\n\n```sh\n$ bundle exec i18n-tasks mv \"{:}.contents.{*}_body\" \"\\1.attributes.\\2.body\"\n\ncar.contents.name_body ⮕ car.attributes.name.body\ncar.contents.description_body ⮕ car.attributes.description.body\ntruck.contents.name_body ⮕ truck.attributes.name.body\ntruck.contents.description_body ⮕ truck.attributes.description.body\n```\n\n#### Custom adapters\n\nIf you store data somewhere but in the filesystem, e.g. in the database or mongodb, you can implement a custom adapter.\nIf you have implemented a custom adapter please share it on [the wiki][wiki].\n\n#### Rails credentials\n\nIf you use Rails credentials and want to load e.g. credentials for translation backends, convert your `i18n-tasks.yml` to `i18n-tasks.yml.erb` and add\na `require \".\u002Fconfig\u002Fapplication\"` line to load Rails.\n\n```yaml\n# config\u002Fi18n-tasks.yml.erb\n\u003C% require \".\u002Fconfig\u002Fapplication\" %>\n\n# ...\n\ntranslation:\n  backend: google\n  google_translate_api_key: \u003C%= Rails.application.credentials.google_translate_api_key %>\n```\n\n### Usage search\n\ni18n-tasks uses an AST scanner for `.rb` and `.html.erb` files, and a regexp scanner for all other files.\nNew scanners can be added easily: please refer to [this example](https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Fwiki\u002FA-custom-scanner-example).\n\nSee the `search` section in the [config file][config] for all available configuration options.\nNB: By default, only the `app\u002F` directory is searched.\n\n#### Prism-based scanner\n\nThere is a scanner based on [Prism](https:\u002F\u002Fgithub.com\u002Fruby\u002Fprism) usable in two different modes.\n\n- `rails` mode parses Rails code and handles context such as controllers, before_actions, model translations and more.\n- `ruby` mode parses Ruby code only, and works similar to the existing whitequark\u002Fparser-implementation.\n- The parser is used for both ruby and ERB files.\n\n##### `rails` mode\n\nIt handles the following cases:\n\n- Translations called in `before_actions`\n- Translations called in nested methods\n- `Model.human_attribute_name` calls\n- `Model.model_name.human` calls\n\nEnable it by adding the following to your `config\u002Fi18n-tasks.yml`:\n\n```yaml\nsearch:\n  prism: \"rails\"\n```\n\n##### `ruby` mode\n\nIt finds all `I18n.t`, `I18n.translate`, `t` and `translate` calls in Ruby code. Enable it by adding:\n\n```yaml\nsearch:\n  prism: \"ruby\"\n```\n\nThe goal is to replace the whitequark\u002Fparser-based scanner with this one in the future.\n\n##### Help us out with testing\n\nPlease install the latest version of the gem and run `bundle exec i18n-tasks check-prism` which will parse everything with the whitequark\u002Fparser-based scanner and then everything with the Prism-scanner and try to compare the results.\n\nOpen up issues with any parser crashes, missed translations or false positives.\n\n### Fine-tuning\n\nAdd hints to static analysis with magic comment hints (lines starting with `(#|\u002F) i18n-tasks-use` by default):\n\n```ruby\n# i18n-tasks-use t('activerecord.models.user') # let i18n-tasks know the key is used\nUser.model_name.human\n```\n\nYou can also explicitly ignore keys appearing in locale files via `ignore*` settings.\n\nIf you have helper methods that generate translation keys, such as a `page_title` method that returns `t '.page_title'`,\nor a `Spree.t(key)` method that returns `t \"spree.#{key}\"`, use the built-in `PatternMapper` to map these.\n\nFor more complex cases, you can implement a [custom scanner][custom-scanner-docs].\n\nSee the [config file][config] to find out more.\n\n### Environment variables & dotenv\n\ni18n-tasks supports loading environment variables from `.env` files using the [dotenv](https:\u002F\u002Fgithub.com\u002Fbkeepers\u002Fdotenv) gem.\nThis is particularly useful for storing translation API keys and other sensitive configuration.\n\nIf you have `dotenv` in your Gemfile, i18n-tasks will automatically load environment variables from `.env` files\nbefore executing commands. This means you can store your API keys in a `.env` file:\n\n```sh\n# .env\nGOOGLE_TRANSLATE_API_KEY=your_google_api_key\nDEEPL_AUTH_KEY=your_deepl_api_key\nOPENAI_API_KEY=your_openai_api_key\n```\n\nThe dotenv integration works seamlessly – no additional configuration is required. If `dotenv` is not available,\ni18n-tasks will continue to work normally using system environment variables.\n\n## Translation backends\n\n### Google Translate\n\n`i18n-tasks translate-missing` requires a Google Translate API key, get it at [Google API Console](https:\u002F\u002Fcode.google.com\u002Fapis\u002Fconsole).\n\nWhere this key is depends on your Google API console:\n\n- Old console: API Access -> Simple API Access -> Key for server apps.\n- New console: Nav Menu -> APIs & Services -> Credentials -> Create Credentials -> API Keys -> Restrict Key -> Cloud Translation API\n\nIn both cases, you may need to create the key if it doesn't exist.\n\nPut the key in `GOOGLE_TRANSLATE_API_KEY` environment variable or in the config file.\n\n```yaml\n# config\u002Fi18n-tasks.yml\ntranslation:\n  backend: google\n  google_translate_api_key: \u003CGoogle Translate API key>\n```\n\nor via environment variable:\n\n```sh\nGOOGLE_TRANSLATE_API_KEY=\u003CGoogle Translate API key>\n```\n\n### DeepL\n\n`i18n-tasks translate-missing` requires a DeepL API key. DeepL offers both a Pro plan and a [Free plan](https:\u002F\u002Fwww.deepl.com\u002Fen\u002Fpro#api) (limited to 500,000 characters\u002Fmonth). Get your API key at [DeepL](https:\u002F\u002Fwww.deepl.com\u002Fen\u002Fpro#api). You can specify alias locales if you only use the simple locales internally.\n\n```yaml\n# config\u002Fi18n-tasks.yml\ntranslation:\n  backend: deepl\n  deepl_api_key: \u003CDeepL API key>\n  deepl_host: \u003Coptional, see note below>\n  deepl_version: \u003Coptional>\n  deepl_glossary_ids:\n    - uuid\n  deepl_options:\n    formality: prefer_less\n  deepl_locale_aliases:\n    en: en-us\n    pt: pt-br\n```\n\nor via environment variables:\n\n```bash\nDEEPL_AUTH_KEY=\u003CDeepL API key>\nDEEPL_HOST=\u003Coptional, see note below>\nDEEPL_VERSION=\u003Coptional>\n```\n\n> **Free API:** If you are using a DeepL Free account, set `deepl_host` to `https:\u002F\u002Fapi-free.deepl.com` (or set the `DEEPL_HOST` environment variable).\n>\n> ```yaml\n> translation:\n>   deepl_api_key: \"your-free-api-key\"\n>   deepl_host: \"https:\u002F\u002Fapi-free.deepl.com\"\n>   deepl_version: \"v2\"\n> ```\n\n### Yandex\n\n`i18n-tasks translate-missing` requires a Yandex API key, get it at [Yandex](https:\u002F\u002Ftech.yandex.com\u002Ftranslate).\n\n```yaml\n# config\u002Fi18n-tasks.yml\ntranslation:\n  backend: yandex\n  yandex_api_key: \u003CYandex API key>\n```\n\nor via environment variable:\n\n```sh\nYANDEX_API_KEY=\u003CYandex API key>\n```\n\n### OpenAI\n\n`i18n-tasks translate-missing` requires an OpenAI API key, get it at [OpenAI](https:\u002F\u002Fopenai.com\u002F).\n\n```yaml\n# config\u002Fi18n-tasks.yml\ntranslation:\n  backend: openai\n  openai_api_key: \u003COpenAI API key>\n  openai_model: \u003Coptional>\n```\n\nor via environment variable:\n\n```sh\nOPENAI_API_KEY=\u003COpenAI API key>\nOPENAI_MODEL=\u003Coptional>\n```\n\n### watsonx\n\n`i18n-tasks translate-missing` requires a watsonx project and an API key, get it at [IBM watsonx](https:\u002F\u002Fwww.ibm.com\u002Fwatsonx\u002F).\n\n```yaml\n# config\u002Fi18n-tasks.yml\ntranslation:\n  backend: watsonx\n  watsonx_api_key: \u003Cwatsonx API key>\n  watsonx_project_id: \u003Cwatsonx project id>\n  watsonx_model: \u003Coptional>\n```\n\nor via environment variable:\n\n```sh\nWATSONX_API_KEY=\u003Cwatsonx API key>\nWATSONX_PROJECT_ID=\u003Cwatsonx project id>\nWATSONX_MODEL=\u003Coptional>\n```\n\n## Features & limitations\n\n`i18n-tasks` uses an AST scanner for `.rb` and `.html.erb` files, and a regexp-based scanner for other files, such as `.haml`.\n\n### Relative keys\n\n`i18n-tasks` offers support for relative keys, such as `t '.title'`.\n\n✔ Keys relative to the file path they are used in (see [Usage search](#usage-search)) are supported.\n\n✔ Keys relative to `controller.action_name` in Rails controllers are supported. The closest `def` name is used.\n\n### Plural keys\n\n✔ Plural keys, such as `key.{one,many,other,...}` are fully supported.\n\n### Reference keys\n\n✔ Reference keys (keys with `:symbol` values) are fully supported. These keys are copied as-is in\n`add\u002Ftranslate-missing`, and can be looked up by reference or value in `find`.\n\n### Dynamic keys\n\nBy default, dynamic keys such as `t \"cats.#{cat}.name\"` are not recognized.\nI encourage you to mark these with [i18n-tasks-use hints](#fine-tuning).\n\nAlternatively, you can enable dynamic key inference by setting `search.strict` to `false` in the config. In this case,\nall the dynamic parts of the key will be considered used, e.g. `cats.tenderlove.name` would not be reported as unused.\nNote that only one section of the key is treated as a wildcard for each string interpolation; i.e. in this example,\n`cats.tenderlove.special.name` _will_ be reported as unused.\n\n### I18n.localize\n\n`I18n.localize` is not supported, use [i18n-tasks-use hints](#fine-tuning).\nThis is because the key generated by `I18n.localize` depends on the type of the object passed in and thus cannot be inferred statically.\n\n### `t()` keyword arguments\n\n✔ `scope` keyword argument is fully supported by the AST scanner, and also by the Regexp scanner but only when it is the first argument.\n\n✔ `default` argument can be used to pre-fill locale files (AST scanner only).\n\n### Unexpected normalization\n\n`i18n-tasks` uses a YAML parser and emitter called `Psych` under the hood. `Psych` has its own heuristic on when\nto use `|`, `>`, or `\"\"` for multi-line strings. This can have some unexpected consequences, e.g. when normalizing:\n\n```yaml\na: |\n  Lorem ipsum dolor sit amet, consectetur\n  Lorem ipsum dolor sit amet, consectetur\nb: |\n  Lorem ipsum dolor sit amet, consectetur\n  Lorem ipsum dolor sit amet, consectetur\n```\n\nwe get the result:\n\n```yaml\na: |\n  Lorem ipsum dolor sit amet, consectetur\n  Lorem ipsum dolor sit amet, consectetur\nb: \"Lorem ipsum dolor sit amet, consectetur \\nLorem ipsum dolor sit amet, consectetur\\n\"\n```\n\nThe only difference between `a` and `b` is that `b` has an extra trailing space in each line.\nThis is an unfortunate side effect of `i18n-tasks` using `Psych`.\n\n## Advanced\n\n### Interactive console\n\n`bundle exec i18n-tasks irb` starts an IRB session in i18n-tasks context. Type `guide` for more information.\n\n### CSV import \u002F export\n\nSee [i18n-tasks wiki: CSV import and export tasks](https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Fwiki\u002FCustom-CSV-import-and-export-tasks).\n\n### Add custom tasks\n\nTasks that come with the gem are defined in [lib\u002Fi18n\u002Ftasks\u002Fcommand\u002Fcommands](lib\u002Fi18n\u002Ftasks\u002Fcommand\u002Fcommands).\nCustom tasks can be added easily, see the examples [on the wiki](https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Fwiki#custom-tasks).\n\n## Development\n\n- Install dependencies using `bundle install`\n- Run tests using `bundle exec rspec`\n- Install [Overcommit](https:\u002F\u002Fgithub.com\u002Fsds\u002Fovercommit) by running `overcommit --install`\n\n### Skip Overcommit hooks\n\n- `SKIP=RuboCop git commit`\n- `OVERCOMMIT_DISABLE=1 git commit`\n\n[MIT license]: \u002FLICENSE.txt\n[ci]: https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Factions\u002Fworkflows\u002Ftests.yml\n[badge-ci]: https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Factions\u002Fworkflows\u002Ftests.yml\u002Fbadge.svg\n[coverage]: https:\u002F\u002Fcodeclimate.com\u002Fgithub\u002Fglebm\u002Fi18n-tasks\n[badge-coverage]: https:\u002F\u002Fapi.codeclimate.com\u002Fv1\u002Fbadges\u002F5d173e90ada8df07cedc\u002Ftest_coverage\n[config]: https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Fblob\u002Fmain\u002Ftemplates\u002Fconfig\u002Fi18n-tasks.yml\n[wiki]: https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Fwiki \"i18n-tasks wiki\"\n[i18n-gem]: https:\u002F\u002Fgithub.com\u002Fsvenfuchs\u002Fi18n \"svenfuchs\u002Fi18n on Github\"\n[screenshot-i18n-tasks]: https:\u002F\u002Fi.imgur.com\u002FXZBd8l7.png \"i18n-tasks screenshot\"\n[screenshot-find]: https:\u002F\u002Fi.imgur.com\u002FVxBrSfY.png \"i18n-tasks find output screenshot\"\n[adapter-example]: https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Fblob\u002Fmain\u002Flib\u002Fi18n\u002Ftasks\u002Fdata\u002Ffile_system_base.rb\n[custom-scanner-docs]: https:\u002F\u002Fgithub.com\u002Fglebm\u002Fi18n-tasks\u002Fwiki\u002FA-custom-scanner-example\n[overcommit]: https:\u002F\u002Fgithub.com\u002Fsds\u002Fovercommit#installation\n","i18n-tasks 是一个用于 Ruby 项目的国际化和本地化管理工具，通过静态代码分析帮助开发者发现并管理缺失或未使用的翻译键。其核心功能包括报告缺失或未使用的键、预填充缺失的键（可选使用 Google Translate 或 DeepL 进行自动翻译）、移除不再使用的键等。技术特点上，它能够对 `I18n.t('some.key')` 类似的调用进行静态分析，从而有效解决运行时因缺少键导致程序崩溃以及冗余键积累的问题。此工具非常适合需要频繁更新多语言支持且希望保持翻译文件整洁高效的 Ruby 项目环境，特别是那些基于 Rails 框架的应用。","2026-06-11 03:15:44","top_language"]