{"action":"created","issue":{"url":"https://api.github.com/repos/jamesarosen/ember-i18n/issues/255","labels_url":"https://api.github.com/repos/jamesarosen/ember-i18n/issues/255/labels{/name}","comments_url":"https://api.github.com/repos/jamesarosen/ember-i18n/issues/255/comments","events_url":"https://api.github.com/repos/jamesarosen/ember-i18n/issues/255/events","html_url":"https://github.com/jamesarosen/ember-i18n/issues/255","id":90709566,"number":255,"title":"RFC: support for translations in addons","user":{"login":"jamesarosen","id":2406,"avatar_url":"https://avatars.githubusercontent.com/u/2406?v=3","gravatar_id":"","url":"https://api.github.com/users/jamesarosen","html_url":"https://github.com/jamesarosen","followers_url":"https://api.github.com/users/jamesarosen/followers","following_url":"https://api.github.com/users/jamesarosen/following{/other_user}","gists_url":"https://api.github.com/users/jamesarosen/gists{/gist_id}","starred_url":"https://api.github.com/users/jamesarosen/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jamesarosen/subscriptions","organizations_url":"https://api.github.com/users/jamesarosen/orgs","repos_url":"https://api.github.com/users/jamesarosen/repos","events_url":"https://api.github.com/users/jamesarosen/events{/privacy}","received_events_url":"https://api.github.com/users/jamesarosen/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-06-24T15:27:17Z","updated_at":"2015-08-29T14:17:14Z","closed_at":null,"body":"In the discussion below, I will use two hypothetical addons, *ember-paginate* and *ember-select*.\r\n\r\n## Problem\r\n\r\nCurrently, if an addon wants to provide default translations that the app can consume and optionally override, there are two options:\r\n\r\n### Require App to Manage\r\n\r\nEach addon has an `addon/locales/en/translations.js` file and similar files for all locales it supports. The app must import these in its own translations files:\r\n\r\n```js\r\n// my-app/app/locales/en/translations.js:\r\n\r\nimport paginationTranslations from \"ember-paginate/locales/en/translations\";\r\nimport selectTranslations from \"ember-select/locales/en/translations\";\r\nimport Ember from \"ember\";\r\n\r\nconst translations = {};\r\nEmber.merge(translations, paginationTranslations);\r\nEmber.merge(translations, selectTranslations);\r\n\r\nEmber.merge(translations, {\r\n  \"app.title\": \"My App\"\r\n});\r\n\r\nexport default translations;\r\n```\r\n\r\nThat's a lot of boilerplate, especially since it needs to be repeated for every locale.\r\n\r\n### Addon Injects Translations\r\n\r\nThe addon could inject translations at runtime with an instance-initializer:\r\n\r\n```js\r\n// ember-paginate/app/instance-initializers/ember-paginate.js:\r\nimport en from \"ember-paginate/locales/en/translations.js\";\r\nimport fr from \"ember-paginate/locales/fr/translations.js\";\r\nimport zh from \"ember-paginate/locales/zh/translations.js\";\r\n\r\nexport default {\r\n  name: 'ember-paginate',\r\n  initialize: function({ container }) {\r\n    const i18n = container.lookup('service:i18n');\r\n    i18n.addTranslations(\"en\", en);\r\n    i18n.addTranslations(\"fr\", fr);\r\n    i18n.addTranslations(\"zh\", zh);\r\n  }\r\n};\r\n```\r\n\r\nThat's far better from an app-developer standpoint, but worse for addon authors.\r\n\r\n## Goal\r\n\r\nThe goal of this RFC is to make it so easy for both addon- and app developers to support i18n that they do by default.\r\n\r\n## Proposal\r\n\r\nThe key to this implementation is to loosen the restriction on the names of translation files. *ember-paginate* would have `ember-paginate/app/locales/en/ember-paginate.js`. *ember-select* might have `ember-select/app/locales/en/ember-select.js`.\r\n\r\nIt would then be the responsibility of ember-i18n's `Locale` to merge translations from all of the various packages. The new logic to get the collected translations for locale `ab-CDE` would be\r\n\r\n 1. enumerate `locale:ab-CDE/*`, excluding `locale:ab-CDE/config`\r\n 2. merge those packages in alphabetical order\r\n 3. walk up the locale-specificity to `ab` and repeat\r\n\r\nhttps://github.com/emberjs/ember.js/pull/11393 introduced a new private API, `knownForType`, that would be useful for enumerating these packages.\r\n\r\n### Ancillary Benefits\r\n\r\nThis change would also mean that app authors (or even addon authors) could break up their translations into multiple files. That would aid organization. I have *not yet* evaluated how that might work with pods.\r\n\r\n### Complications\r\n\r\nThere is potential for name collision across addons. It would thus be **strongly recommended** that addons define translations in `my-addon/app/:locale/my-addon.js`.\r\n\r\nThis change would mean there no longer necessarily be a `locale:ab-CDE/translations`. That means that `addTranslations(\"ab-CDE\", {...})` wouldn't have an obvious place to register its translations. We would want translations added through `addTranslations` to override anything from the lookup path. Thus, I propose `addTranslations` looks up or creates `locale:ab-CDE/_runtime` with highest precedence in the merging.\r\n\r\nThis change also suggests a change to the generator. One option would be to have the `locale` generator accept an optional second `package` argument, with the default `translations`. Alternatively, there could be a second `locale-package` or `translations` generator that requires a `package` argument.\r\n\r\n/cc @jkarsrud @rwjblue"},"comment":{"url":"https://api.github.com/repos/jamesarosen/ember-i18n/issues/comments/135989517","html_url":"https://github.com/jamesarosen/ember-i18n/issues/255#issuecomment-135989517","issue_url":"https://api.github.com/repos/jamesarosen/ember-i18n/issues/255","id":135989517,"user":{"login":"rwjblue","id":12637,"avatar_url":"https://avatars.githubusercontent.com/u/12637?v=3","gravatar_id":"","url":"https://api.github.com/users/rwjblue","html_url":"https://github.com/rwjblue","followers_url":"https://api.github.com/users/rwjblue/followers","following_url":"https://api.github.com/users/rwjblue/following{/other_user}","gists_url":"https://api.github.com/users/rwjblue/gists{/gist_id}","starred_url":"https://api.github.com/users/rwjblue/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rwjblue/subscriptions","organizations_url":"https://api.github.com/users/rwjblue/orgs","repos_url":"https://api.github.com/users/rwjblue/repos","events_url":"https://api.github.com/users/rwjblue/events{/privacy}","received_events_url":"https://api.github.com/users/rwjblue/received_events","type":"User","site_admin":false},"created_at":"2015-08-29T14:17:14Z","updated_at":"2015-08-29T14:17:14Z","body":"@jamesarosen - The proposal looks good to me.  We can also work on making `knownForType` public (it is only private because we didn't have other use cases at the time)."}}