{"id":13684254,"url":"https://github.com/ADmad/cakephp-i18n","last_synced_at":"2025-04-30T20:33:35.275Z","repository":{"id":23008036,"uuid":"26358783","full_name":"ADmad/cakephp-i18n","owner":"ADmad","description":"A CakePHP plugin with I18n related tools.","archived":false,"fork":false,"pushed_at":"2024-11-05T12:10:09.000Z","size":194,"stargazers_count":44,"open_issues_count":0,"forks_count":14,"subscribers_count":9,"default_branch":"master","last_synced_at":"2024-11-05T13:27:52.789Z","etag":null,"topics":["cakephp","cakephp-plugin","i18n","php","translation"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ADmad.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","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},"funding":{"github":["ADmad"]}},"created_at":"2014-11-08T11:42:23.000Z","updated_at":"2024-11-05T12:10:13.000Z","dependencies_parsed_at":"2023-09-29T07:36:40.920Z","dependency_job_id":null,"html_url":"https://github.com/ADmad/cakephp-i18n","commit_stats":{"total_commits":196,"total_committers":7,"mean_commits":28.0,"dds":0.08163265306122447,"last_synced_commit":"4208305e454cda236972e346c1fbd45727bb5f4e"},"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADmad%2Fcakephp-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADmad%2Fcakephp-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADmad%2Fcakephp-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ADmad%2Fcakephp-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ADmad","download_url":"https://codeload.github.com/ADmad/cakephp-i18n/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224224786,"owners_count":17276428,"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":["cakephp","cakephp-plugin","i18n","php","translation"],"created_at":"2024-08-02T14:00:31.540Z","updated_at":"2025-04-30T20:33:35.262Z","avatar_url":"https://github.com/ADmad.png","language":"PHP","readme":"# CakePHP plugin for I18n related tools.\n\n[![Build Status](https://img.shields.io/github/actions/workflow/status/ADmad/cakephp-i18n/ci.yml?branch=master\u0026style=flat-square)](https://github.com/ADmad/cakephp-i18n/actions/workflows/ci.yml?query=branch%3Amaster)\n[![Coverage Status](https://img.shields.io/codecov/c/github/ADmad/cakephp-i18n.svg?style=flat-square)](https://codecov.io/github/ADmad/cakephp-i18n)\n[![Total Downloads](https://img.shields.io/packagist/dt/ADmad/cakephp-i18n.svg?style=flat-square)](https://packagist.org/packages/ADmad/cakephp-i18n)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE.txt)\n\n# Intro\n\nThis plugins provides:\n\n- A route class for generating and matching urls with language prefix.\n- A middleware which sets locale using `I18n::setLocale()`\n  based on language prefix in URL and also provides redirection to appropriate\n  URL with language prefix when accessing site root.\n- A class for retrieving translation messages stored in the database instead of using po/mo files.\n- A validation class for auto translating validation message.\n- A widget to generate select box with list of timezone identifiers.\n\n## Installation\n\n```bash\ncomposer require admad/cakephp-i18n\n```\n\n## Usage\n\nLoad the plugin by running command:\n\n```bash\nbin/cake plugin load ADmad/I18n\n```\n\nThe plugin contains multiple classes useful for internationalization. You can pick\nand chose the ones you require.\n\n### I18nRoute\n\nThe `I18nRoute` class helps generating language prefixed routes of style\n`/{lang}/{controller}/{action}`.\n\nFor e.g. you can add routes to your `routes.php` similar to the ones shown below:\n\n```php\n$routes-\u003escope('/', function ($routes) {\n    $routes-\u003econnect(\n        '/{controller}',\n        ['action' =\u003e 'index'],\n        ['routeClass' =\u003e 'ADmad/I18n.I18nRoute']\n    );\n    $routes-\u003econnect(\n        '/{controller}/{action}/*',\n        [],\n        ['routeClass' =\u003e 'ADmad/I18n.I18nRoute']\n    );\n});\n```\n\nFragment `/{lang}` will be auto prefixed to the routes which allows matching\nURLs like `/en/posts`, `/en/posts/add` etc. The `lang` element is persisted so\nthat when generating URLs if you don't provide the `lang` key in URL array it\nwill be automatically added based on current URL.\n\nWhen connecting the routes you can use `lang` key in options to provide regular\nexpression to match only languages which your app supports. Or your can set\nconfig value `I18n.languages`, which the route class will use to auto generate\nregex for `lang` element matching:\n\n```php\n// In your config/app.php\n    ...\n    'I18n' =\u003e [\n        'languages' =\u003e ['en', 'fr', 'de']\n    ]\n    ...\n```\n\nNote: `I18nRoute` extends core's `DashedRoute` so the URL fragments will be\ninflected accordingly.\n\n### I18nMiddleware\n\nWhile not necessary, one would generally use the `I18nMiddleware` too when using\nlanguage prefixed routes with the help of `I18nRoute`.\n\nYou can setup the `I18nMiddleware` in your `src/Application::middleware()` as\nshown:\n\n```php\n$middlware-\u003eadd(new \\ADmad\\I18n\\Middleware\\I18nMiddleware([\n    // If `true` will attempt to get matching languges in \"languages\" list based\n    // on browser locale and redirect to that when going to site root.\n    'detectLanguage' =\u003e true,\n    // Default language for app. If language detection is disabled or no\n    // matching language is found redirect to this language\n    'defaultLanguage' =\u003e 'en',\n    // Languages available in app. The keys should match the language prefix used\n    // in URLs. Based on the language the locale will be also set.\n    'languages' =\u003e [\n        'en' =\u003e ['locale' =\u003e 'en_US'],\n        'fr' =\u003e ['locale' =\u003e 'fr_FR'],\n    ],\n]));\n```\n\nThe keys of `languages` array are the language prefixes you use in your URL.\n\nTo ensure that the `lang` router param is available, you must add this middleware\n*after* adding CakePHP's default routing middleware (i.e. after `-\u003eadd(new RoutingMiddleware($this))`).\n\nThe middleware does basically two things:\n\n1. When accessing site root `/` it redirects the user to a language prefixed URL,\n   for e.g. `/en`. The langauge it redirects to depends on the configuration keys\n   `detectLanguage` and `defaultLanguage` shown above.\n\n   Now in order to prevent CakePHP from complaining about missing route for `/`,\n   you must connect a route for `/` to a controller action. That controller action\n   will never be actually called as the middleware will intercept and redirect\n   the request.\n\n   For e.g. `$routes-\u003econnect('/', ['controller' =\u003e 'Foo']);`\n\n2. When accesing any URL with language prefix it sets the app's locale based\n   on the prefix. For that it checks the value of `lang` route element in current\n   request's params. This route element would be available if the matched route\n   has been connected using the `I18nRoute`.\n\n   Using the array provided for the `languages` key it sets the `App.language`\n   config to the language prefix through `Configure::write()` and the value of `locale`\n   is used for the `I18n::setLocale()` call.\n\n### DbMessagesLoader\n\nBy default CakePHP uses `.po` files to store the static string translations. If\nfor whatever reason you can't/don't want to use `.po` files, you can use the\n`DbMessagesLoader` to store the translation messages in the database instead.\nPersonally I belive having the messages in a table instead of `.po` files makes\nit much easier to make a web interface for managing translations.\n\nTo use this class first create the `i18n_messages` database table using the sql\nfile provided in the plugin's `config` folder.\n\nAdd code similar to what's shown below in your app's `config/bootstrap.php`:\n\n```php\n// NOTE: This is should be done below Cache config setup.\n\n// Configure `I18n` to use `DbMessagesLoader` for the `default` domain. You need to do\n// this for each domain separately.\n\\Cake\\I18n\\I18n::config('default', function ($domain, $locale) {\n    return new \\ADmad\\I18n\\I18n\\DbMessagesLoader(\n        $domain,\n        $locale\n    );\n});\n```\n\nNow you can use the translation functions like `__()` etc. as you normally would.\nThe `I18n` class will fetch the required translations from the `i18n_messages`\ntable instead of `.po` files.\n\nUse the `admad/i18n extract` command to extract the translation messages from your\ncode files and populate the translations table. Updating the database records with\ntranslations for each language is upto you.\n\n```bash\nbin/cake admad/i18n extract\n```\n\nThe extract command needs the list of languages/locales to populate the  `i18n_messages`\ntable. This can be done by setting the `I18n.languages` config **or** by specifying\nthe languages list using the `languages` option.\n\n```php\n// In your config/app.php\n    ...\n    'I18n' =\u003e [\n        'languages' =\u003e ['en', 'fr', 'de']\n    ]\n    ...\n```\n\n```bash\nbin/cake admad/i18n extract --languages en,fr,de\n```\n\nYou can run the command multiple times as needed. It will add new messages it\nfinds to the tables, keeping the ones already present untouched.\n\n### TimezoneWidget\n\nIn your `AppView::initialize()` configure the `FormHelper` to use `TimezoneWidget`.\n\n```php\n// src/View/AppView.php\npublic function initialize(): void\n{\n    $this-\u003eloadHelper('Form', [\n        'widgets' =\u003e [\n            'timezone' =\u003e ['ADmad/I18n.Timezone'],\n        ],\n    ]);\n}\n```\n\nYou can generate a select box with timezone identifiers like:\n\n```php\n// Generates select box with list of all timezone identifiers grouped by regions.\n$this-\u003eForm-\u003econtrol('fieldname', ['type' =\u003e 'timezone']);\n\n// Generates select box with list of timezone identifiers for specified regions.\n$this-\u003eForm-\u003econtrol('fieldname', [\n    'type' =\u003e 'timezone',\n    'options' =\u003e [\n        'Asia' =\u003e DateTimeZone::ASIA,\n        'Europe' =\u003e DateTimeZone::EUROPE,\n    ],\n]);\n```\n\nAs shown in example above note that unlike normal select box, `options` is now\nan associative array of valid timezone regions where the key will be used as\n`optgroup` in the select box.\n","funding_links":["https://github.com/sponsors/ADmad"],"categories":["I18n"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FADmad%2Fcakephp-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FADmad%2Fcakephp-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FADmad%2Fcakephp-i18n/lists"}