{"id":20340932,"url":"https://github.com/leancodepl/poe2arb","last_synced_at":"2025-04-11T23:31:11.105Z","repository":{"id":63359538,"uuid":"438799262","full_name":"leancodepl/poe2arb","owner":"leancodepl","description":"POEditor JSON to Flutter ARB converter","archived":false,"fork":false,"pushed_at":"2024-04-03T15:03:27.000Z","size":717,"stargazers_count":31,"open_issues_count":4,"forks_count":0,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-06-19T13:37:10.507Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leancodepl.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-15T23:12:14.000Z","updated_at":"2024-05-31T21:50:44.000Z","dependencies_parsed_at":"2024-04-03T15:43:05.623Z","dependency_job_id":null,"html_url":"https://github.com/leancodepl/poe2arb","commit_stats":{"total_commits":176,"total_committers":6,"mean_commits":"29.333333333333332","dds":"0.23863636363636365","last_synced_commit":"da5e2160454b4b8d73e44ed2e34b41985248b97d"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancodepl%2Fpoe2arb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancodepl%2Fpoe2arb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancodepl%2Fpoe2arb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leancodepl%2Fpoe2arb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leancodepl","download_url":"https://codeload.github.com/leancodepl/poe2arb/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248494815,"owners_count":21113504,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-14T21:24:43.859Z","updated_at":"2025-04-11T23:31:11.079Z","avatar_url":"https://github.com/leancodepl.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# poe2arb\n\n[![Latest GitHub release][github-release-img]][github-release-link]\n[![CI status(main branch)][ci-status-img]][ci-status-link]\n\n![][screenshot-img]\n\u003c/div\u003e\n\n`poe2arb` is a CLI tool that lets the POEditor work with Flutter's native\nlocalization solution (`flutter gen-l10n`).\n\n## Installation\n\nYou can download latest or historical binary straight from the [GitHub\nreleases][releases] artifacts or using Homebrew:\n\n```\nbrew tap leancodepl/poe2arb\nbrew install poe2arb\n```\n\n### `POEDITOR_TOKEN`\n\nThe `poe2arb poe` command requires a POEditor read-only API token.\nIt's available in [Account settings \u003e API access][poeditor-tokens].\n\nYou can export this token in your `~/.bashrc` or `~/.zshrc` so that it's always\navailable:\n\n```bash\nexport POEDITOR_TOKEN=\"YOUR_API_TOKEN_HERE\"\n```\n\n## Usage\n\n`poe2arb` operates on POEditor's _JSON_ (not _JSON key-value_) export file\nformat.\n\n### Full POEditor integration\n\n`poe2arb poe` command is your Swiss Army Knife enabling integrating POEditor\ninto your Flutter workspace in one command:\n\n1. Fetches all project languages from API.\n2. Downloads JSON exports for all languages from API.\n3. Converts JSON exports to ARB format.\n4. Saves converted ARB files to the output directory.\n\n#### Options\n\nIf a command-line flag is not specified, an environment variable is used, then `l10n.yaml` option, then it fallbacks to default.\n\n| Description                                                                                                       | Flag                   | Env              | `l10n.yaml`            |\n|-------------------------------------------------------------------------------------------------------------------|------------------------|------------------|------------------------|\n| **Required.** POEditor project ID. It is visible in the URL of the project on POEditor website.                   | `-p`\u003cbr\u003e`--project-id` |                  | `poeditor-project-id`  |\n| **Required.** POEditor API read-only access token. Available in [Account settings \u003e API access][poeditor-tokens]. | `-t`\u003cbr\u003e`--token`      | `POEDITOR_TOKEN` |                        |\n| ARB files output directory.\u003cbr\u003eDefaults to current directory.                                                     | `-o`\u003cbr\u003e`--output-dir` |                  | `arb-dir`              |\n| Exported languages override.\u003cbr\u003eDefaults to using all languages from POEditor.                                    | `--langs`              |                  | `poeditor-langs`       |\n| Term prefix, used to filter generated messages.\u003cbr\u003eDefaults to empty.                                             | `--term-prefix`        |                  | `poeditor-term-prefix` |\n\n### Conversion\n\n`poe2arb convert` command only converts the POE export to ARB format. Refer to\n[Supported features](#syntax--supported-features) section.\n\nFor conversion, you need to pass the translation file language in the\n`--lang/-l` flag.\n\nBy default, a template ARB file is generated. So no empty message is skipped and attributes are generated. If you want to skip that, pass `--no-template` flag.\n\nYou may filter terms with `--term-prefix`. Defaults to empty (no prefix).\n\nCurrently, only an stdin/stdout is supported for the `poe2arb convert` command.\n\n```\npoe2arb convert io --lang en \u003c Hello_World_English.json \u003e lib/l10n/app_en.arb\n```\n\n### Seeding POEditor project\n\n\u003e [!WARNING]\n\u003e **EXPERIMENTAL FEATURE**\n\nIf you're setting up a project from some template code, you probably already have some ARB files that need\nto be imported into the POEditor project. Using the POEditor's built-in tool won't give a satisfying result,\nas it will completely ignore placeholders along with their types and other parameters, as well as it won't\n\"understand\" the plural ICU message format. This is where `poe2arb seed` command comes into place.\n\n`poe2arb seed` command uses the same configuration as the `poe2arb poe`, but **it needs API access token with a write\naccess**, to create language in the project if needed, and to upload the translations and terms.\n\nThis command is meant only for seeding the project, i.e. setting its first contents. It won't override your existing\ntranslations and won't delete anything. That said, it should still be run with caution and running this on projects\nwith already populated translations is inadvisable.\n\n## Syntax \u0026 supported features\n\n\u003e [!IMPORTANT]\n\u003e Term name must be a valid Dart field name, additionaly, it must start with a lowercase letter ([Flutter's constraint][term-name-constraint]).\n\n### Term prefix filtering\n\nIf you wish to use one POEditor project for multiple packages, ideally you do not want\none package's terms to pollute all other packages. This is what term prefixes are for.\n\nTerm names in POEditor can be defined starting with a prefix (only letters), followed by a colon `:`.\nE.g. `loans:helpPage_title` or `design_system:modalClose`. Then, in your `l10n.yaml` or with the `--term-prefix` flag you may\ndefine which terms should be imported, filtered by the prefix.\n\nIf you don't pass a prefix to `poe2arb` (or pass an empty one), it will only import the terms that have no prefix. If you pass\nprefix to `poe2arb`, it will import only the terms with this prefix.\n\n\u003cdetails\u003e\u003csummary\u003eExamples\u003c/summary\u003e\n\n| Term name in POEditor | `--term-prefix` or\u003cbr\u003e`poeditor-term-prefix` (`l10n.yaml`) | Message name in ARB |\n|-----------------------|------------------------------------------------------------|---------------------|\n| `appTitle`            | none                                                       | `appTitle`          |\n| `somePrefix:appTitle` | none                                                       | not imported        |\n| `appTitle`            | `somePrefix`                                               | not imported        |\n| `somePrefix:appTitle` | `somePrefix`                                               | `appTitle`          |\n\n\u003c/details\u003e\n\n### Placeholders\n\nPlaceholders can be as simple as a text between brackets, but they can also be\nwell-defined with a type and format, to make use of date and number formatting.\n\nPlaceholders that have no type specified will have a `String` type, as opposed to Flutter's `Object` default type.\n\nEach unique placeholder must be **defined**  only once. I.e. for one `{placeholder,String}` you may have many\n`{placeholder}` (that use the same definition), but no other `{placeholder,String}` must be found in the term.\n\nAvailable placeholder types:\n* `String` - default when no type is specified.\n* `Object` - is `toString()`ed.\n* `DateTime`\n\n  Placeholders with type `DateTime` must have a format specified. The valid values are the names of\n  [the `DateFormat` constructors][dateformat-constructors], e.g. `yMd`, `jms`, or `EEEEE`.\n* `num`, `int`, `double`\n\n  Placeholders with type `num`, `int`, or `double` **may have\\*** a format specified. The valid values are the names\n  of [the `NumberFormat` constructors][numberformat-constructors], e.g. `decimalPattern`, or `percentPattern`.\n  In plurals, the `count` placeholder must be of `int` or `num` type. It can be left with no definition.\n\n  Number placeholders without a specified format will be simply `toString()`ed.\n\n**Only template files can define placeholders with their type and format.** In non-template languages, placeholders' types and formats\nare ignored and no logical errors are reported.\n\n\u003e [!NOTE]\n\u003e \\*If you're using Flutter 3.5 or older, you need to specify format for numeric placeholders.\n\u003e Otherwise `flutter gen-l10n` will fail. You can look at the legacy placeholder syntax diagrams\n\u003e [for placeholders here][flutter35-placeholders-diagram] and for [plural's `count` placeholders here][flutter35-count-placeholders-diagram].\n\n#### Examples\n\nBelow are some examples of strings that make use of placeholders. Simple and well-defined.\n\n```\nHello, {name}!\n```\n\n```\nHello, {name,String}!\n```\n\n```\nYou have {coins,int,decimalPattern} coins left in your {wallet,String} wallet.\n```\n\n```\nlast modified on {date,DateTime,yMMMEEEEd}\n```\n\n#### Placeholder syntax diagram\n\n![][placeholder-diagram-img]\n\n##### `count` placeholder syntax diagram\n\n![][count-placeholder-diagram-img]\n\n\n### Plurals\n\nPOEditor plurals are also supported. Simply mark the the term as plural and\ngive it _any_ name (it's never used, but required by POEditor to enable plurals\nfor the term).\n\nIn translations, a `{count}` placeholder can be used. You can use other placeholders too. Example:\n\n```\none:    Andy has 1 kilogram of {fruit}.\nother:  Andy has {count} kilograms of {fruit}.\n```\n\nYou must provide at least `other` plural category for your translations, otherwise it won't be converted.\n\n## Constraining version for a Flutter project\n\nYou can constrain poe2arb version by specifying `poe2arb-version` option in `l10n.yaml`.\n\n```yaml\n# Available formats:\npoe2arb-version: \"0.5.1\"          # Specific version\npoe2arb-version: \"\u003e=0.5.1, \u003c0.7\"  # Version range\npoe2arb-version: \"\u003e0.5.1\"         # Minimum version\npoe2arb-version: \"\u003c=0.7\"          # Maximum version\n```\n\nYou can find more information about version constraints format [here][go-version].\n\n## Contributing\n\n### Formatting\n\nWe use [gofumpt][gofumpt], which is a superset of [gofmt][gofmt].\n\nTo make `gopls` in VS Code use `gofumpt`, add this to your settings:\n\n```json\n\"gopls\": {\n    \"formatting.gofumpt\": true\n},\n```\n\n### Linting\n\nWe use [staticcheck][staticcheck] with all checks enabled.\n\nTo make VS Code use `staticcheck`, add this to your settings:\n\n```json\n\"go.lintTool\": \"staticcheck\",\n\"go.lintFlags\": [\"-checks=all\"],\n```\n\n### Building\n\nAll you need is Go 1.20.\n\n```\ngo build .\n```\n\n### Releasing\n\nCreate a _lightweight_ git tag and push it. GitHub Actions with a GoReleaser\nworkflow will take care of the rest.\n\n```\ngit tag v0.1.1\ngit push origin v0.1.1\n```\n\n[github-release-link]: https://github.com/leancodepl/poe2arb/releases\n[github-release-img]: https://img.shields.io/github/v/release/leancodepl/poe2arb?label=version\u0026sort=semver\n[ci-status-link]: https://github.com/leancodepl/poe2arb/actions/workflows/go-test.yml\n[ci-status-img]: https://img.shields.io/github/actions/workflow/status/leancodepl/poe2arb/go-test.yml?branch=main\n[screenshot-img]: art/terminal-screenshot.png\n[releases]: https://github.com/leancodepl/poe2arb/releases\n[poeditor-tokens]: https://poeditor.com/account/api\n[term-name-constraint]: https://github.com/flutter/flutter/blob/ce318b7b539e228b806f81b3fa7b33793c2a2685/packages/flutter_tools/lib/src/localizations/gen_l10n.dart#L868-L886\n[dateformat-constructors]: https://pub.dev/documentation/intl/latest/intl/DateFormat-class.html#constructors\n[numberformat-constructors]: https://pub.dev/documentation/intl/latest/intl/NumberFormat-class.html#constructors\n[flutter35-placeholders-diagram]: https://github.com/leancodepl/poe2arb/blob/24be17d6721698526c879b3fada87183b359e8e8/art/placeholder-syntax.svg\n[flutter35-count-placeholders-diagram]: https://github.com/leancodepl/poe2arb/blob/24be17d6721698526c879b3fada87183b359e8e8/art/count-placeholder-syntax.svg\n[placeholder-diagram-img]: art/placeholder-syntax.svg\n[count-placeholder-diagram-img]: art/count-placeholder-syntax.svg\n[go-version]: https://github.com/hashicorp/go-version\n[gofumpt]: https://github.com/mvdan/gofumpt\n[gofmt]: https://pkg.go.dev/cmd/gofmt\n[staticcheck]: https://staticcheck.io\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleancodepl%2Fpoe2arb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleancodepl%2Fpoe2arb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleancodepl%2Fpoe2arb/lists"}