├── .github └── workflows │ ├── ci.yml │ └── publish-book.yml ├── .gitignore ├── Cargo.toml ├── LICENSE.md ├── README.md ├── docs ├── book │ ├── .gitignore │ ├── README.md │ └── src │ │ ├── 01_introduction.md │ │ ├── 02_getting_started.md │ │ ├── 06_features.md │ │ ├── SUMMARY.md │ │ ├── appendix_i18n_ally.md │ │ ├── declare │ │ ├── 01_key_value.md │ │ ├── 02_interpolation.md │ │ ├── 03_plurals.md │ │ ├── 04_ranges.md │ │ ├── 05_subkeys.md │ │ ├── 06_foreign_keys.md │ │ ├── 07_mix_kinds.md │ │ ├── 08_formatters.md │ │ └── README.md │ │ ├── infos │ │ ├── 01_locale_resol.md │ │ └── README.md │ │ ├── reduce_size │ │ ├── 01_datagen.md │ │ ├── 02_dynamic_load.md │ │ └── README.md │ │ ├── setting_up │ │ ├── 01_configuration.md │ │ ├── 02_file_structure.md │ │ ├── 03_namespaces.md │ │ ├── 04_inheritance.md │ │ └── README.md │ │ └── usage │ │ ├── 01_load.md │ │ ├── 02_context.md │ │ ├── 03_subcontext.md │ │ ├── 04_t_macro.md │ │ ├── 05_td_macro.md │ │ ├── 06_td_string_macro.md │ │ ├── 07_router.md │ │ ├── 08_scoping.md │ │ ├── 09_t_format.md │ │ ├── 10_t_plural.md │ │ ├── 11_const_access.md │ │ ├── 12_serverfn.md │ │ └── README.md └── expanded_macros │ ├── load_locales.md │ ├── scope.md │ ├── t.md │ └── td.md ├── examples ├── csr │ ├── counter │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── counter_icu_datagen │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── counter_plurals │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── counter_ranges │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── interpolation │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── namespaces │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en │ │ │ │ ├── change_locale.json │ │ │ │ └── counter.json │ │ │ └── fr │ │ │ │ ├── change_locale.json │ │ │ │ └── counter.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── routing_csr │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── subcontext │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── subkeys │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ └── yaml │ │ ├── .gitignore │ │ ├── .vscode │ │ ├── extensions.json │ │ ├── i18n-ally-custom-framework.yml │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ ├── en.yaml │ │ └── fr.yaml │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ └── favicon.ico │ │ ├── src │ │ ├── app.rs │ │ └── main.rs │ │ └── style │ │ └── main.scss ├── dynamic_load │ ├── axum_island │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── csr_counter │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── index.html │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── hello_world_actix │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── hello_world_axum │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ ├── fileserv.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ └── namespaces │ │ ├── .gitignore │ │ ├── .vscode │ │ ├── extensions.json │ │ ├── i18n-ally-custom-framework.yml │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ └── example.spec.ts │ │ ├── locales │ │ ├── en │ │ │ ├── change_locale.json │ │ │ └── counter.json │ │ └── fr │ │ │ ├── change_locale.json │ │ │ └── counter.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ └── favicon.ico │ │ ├── src │ │ ├── app.rs │ │ ├── fileserv.rs │ │ ├── lib.rs │ │ └── main.rs │ │ └── style │ │ └── main.scss ├── ssr │ ├── axum_island │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── hello_world_actix │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── hello_world_axum │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ ├── fileserv.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ ├── routing_ssr │ │ ├── .gitignore │ │ ├── .vscode │ │ │ ├── extensions.json │ │ │ ├── i18n-ally-custom-framework.yml │ │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── e2e │ │ │ └── example.spec.ts │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ ├── fileserv.rs │ │ │ ├── lib.rs │ │ │ └── main.rs │ │ └── style │ │ │ └── main.scss │ └── workspace │ │ ├── .gitignore │ │ ├── .vscode │ │ ├── extensions.json │ │ ├── i18n-ally-custom-framework.yml │ │ └── settings.json │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── client │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── locales │ │ │ ├── en.json │ │ │ └── fr.json │ │ ├── public │ │ │ └── favicon.ico │ │ ├── src │ │ │ ├── app.rs │ │ │ └── lib.rs │ │ └── style │ │ │ └── main.scss │ │ ├── e2e │ │ └── example.spec.ts │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── playwright.config.ts │ │ └── server │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ └── src │ │ └── main.rs └── utils │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── src │ └── index.ts │ └── tsconfig.json ├── leptos_i18n ├── .gitignore ├── Cargo.toml └── src │ ├── context.rs │ ├── display.rs │ ├── fetch_locale.rs │ ├── fetch_translations.rs │ ├── langid.rs │ ├── lib.rs │ ├── locale.rs │ ├── locale_traits.rs │ ├── macro_helpers │ ├── formatting │ │ ├── currency.rs │ │ ├── date.rs │ │ ├── datetime.rs │ │ ├── list.rs │ │ ├── mod.rs │ │ ├── nums.rs │ │ └── time.rs │ ├── interpol_args.rs │ ├── mod.rs │ └── scope.rs │ ├── macros.rs │ └── scopes.rs ├── leptos_i18n_build ├── .gitignore ├── Cargo.toml └── src │ ├── datakey.rs │ └── lib.rs ├── leptos_i18n_macro ├── .gitignore ├── Cargo.toml └── src │ ├── data_provider.rs │ ├── lib.rs │ ├── load_locales │ ├── declare_locales.rs │ ├── interpolate.rs │ ├── locale.rs │ ├── mod.rs │ ├── parsed_value.rs │ ├── plurals.rs │ ├── ranges.rs │ ├── tracking.rs │ └── warning.rs │ ├── t_format │ ├── mod.rs │ └── parsed_input.rs │ ├── t_macro │ ├── interpolate.rs │ ├── mod.rs │ └── parsed_input.rs │ ├── t_plural │ ├── mod.rs │ └── parsed_input.rs │ └── utils │ ├── formatter.rs │ ├── mod.rs │ └── scoped.rs ├── leptos_i18n_parser ├── .gitignore ├── Cargo.toml └── src │ ├── lib.rs │ ├── parse_locales │ ├── cfg_file.rs │ ├── error.rs │ ├── locale.rs │ ├── mod.rs │ ├── parsed_value.rs │ ├── plurals.rs │ ├── ranges.rs │ └── warning.rs │ └── utils │ ├── formatter.rs │ ├── key.rs │ └── mod.rs ├── leptos_i18n_router ├── .gitignore ├── Cargo.toml └── src │ ├── components.rs │ ├── lib.rs │ └── routing.rs └── tests ├── common ├── Cargo.toml └── src │ └── lib.rs ├── json ├── .gitignore ├── .vscode │ ├── extensions.json │ ├── i18n-ally-custom-framework.yml │ └── settings.json ├── Cargo.toml ├── README.md ├── locales │ ├── en.json │ └── fr.json └── src │ ├── defaulted.rs │ ├── foreign.rs │ ├── formatting.rs │ ├── lib.rs │ ├── plurals.rs │ ├── ranges.rs │ ├── scoped.rs │ ├── subkeys.rs │ ├── t_format.rs │ ├── t_plural.rs │ └── tests.rs ├── json5 ├── .gitignore ├── .vscode │ ├── extensions.json │ ├── i18n-ally-custom-framework.yml │ └── settings.json ├── Cargo.toml ├── README.md ├── locales │ ├── en.json5 │ └── fr.json5 └── src │ ├── defaulted.rs │ ├── lib.rs │ ├── ranges.rs │ ├── subkeys.rs │ └── tests.rs ├── namespaces ├── .gitignore ├── .vscode │ ├── extensions.json │ ├── i18n-ally-custom-framework.yml │ └── settings.json ├── Cargo.toml ├── README.md ├── locales │ ├── en │ │ ├── first_namespace.json │ │ └── second_namespace.json │ └── fr │ │ ├── first_namespace.json │ │ └── second_namespace.json └── src │ ├── first_ns.rs │ ├── lib.rs │ ├── scoped.rs │ └── second_ns.rs └── yaml ├── .gitignore ├── .vscode ├── extensions.json ├── i18n-ally-custom-framework.yml └── settings.json ├── Cargo.toml ├── README.md ├── locales ├── en.yaml └── fr.yml └── src ├── defaulted.rs ├── lib.rs ├── ranges.rs ├── subkeys.rs └── tests.rs /.github/workflows/publish-book.yml: -------------------------------------------------------------------------------- 1 | name: Deploy book 2 | on: 3 | push: 4 | paths: ["docs/book/**"] 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | permissions: 12 | contents: write # To push a branch 13 | pull-requests: write # To create a PR from that branch 14 | steps: 15 | - uses: actions/checkout@v4 16 | with: 17 | fetch-depth: 0 18 | - name: Install mdbook 19 | run: | 20 | mkdir mdbook 21 | curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.27/mdbook-v0.4.27-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook 22 | echo `pwd`/mdbook >> $GITHUB_PATH 23 | - name: Deploy GitHub Pages 24 | run: | 25 | cd docs/book 26 | mdbook build 27 | git worktree add gh-pages 28 | git config user.name "Deploy book from CI" 29 | git config user.email "" 30 | cd gh-pages 31 | # Delete the ref to avoid keeping history. 32 | git update-ref -d refs/heads/gh-pages 33 | rm -rf * 34 | mv ../book/* . 35 | git add . 36 | git commit -m "Deploy book $GITHUB_SHA to gh-pages" 37 | git push --force --set-upstream origin gh-pages 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | .vscode 4 | publish.ps1 -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "leptos_i18n", 5 | "leptos_i18n_macro", 6 | "leptos_i18n_parser", 7 | "leptos_i18n_build", 8 | "tests/json", 9 | "tests/common", 10 | "tests/namespaces", 11 | "leptos_i18n_router", 12 | ] 13 | exclude = ["examples", "tests"] 14 | 15 | [workspace.package] 16 | version = "0.5.11" 17 | 18 | [workspace.dependencies] 19 | # pin macro and parser version, those don't follow semver internally so a version missmatch with the main crate can cause problems. 20 | leptos_i18n_macro = { path = "./leptos_i18n_macro", default-features = false, version = "=0.5.11" } 21 | leptos_i18n_parser = { path = "./leptos_i18n_parser", default-features = false, version = "=0.5.11" } 22 | leptos_i18n = { path = "./leptos_i18n", default-features = false, version = "0.5.11" } 23 | leptos_i18n_router = { path = "./leptos_i18n_router", version = "0.5.11" } 24 | 25 | # leptos 26 | leptos = { version = "0.7.7", default-features = false } 27 | leptos_router = { version = "0.7.7", default-features = false } 28 | leptos_meta = { version = "0.7.7", default-features = false } 29 | 30 | # icu 31 | icu_locid = { version = "1.5", default-features = false } 32 | icu_provider = { version = "1.5", default-features = false } 33 | fixed_decimal = { version = "0.5", default-features = false } 34 | icu_datagen = { version = "1.5" } 35 | icu_plurals = { version = "1.5", default-features = false } 36 | icu_datetime = { version = "1.5", default-features = false } 37 | icu_calendar = { version = "1.5", default-features = false } 38 | icu_list = { version = "1.5", default-features = false } 39 | icu_decimal = { version = "1.5", default-features = false } 40 | icu_locid_transform = { version = "1.5", default-features = false } 41 | icu_experimental = { version = "0.1.0", default_features = false } 42 | tinystr = "0.7.6" 43 | 44 | # internal use 45 | tests_common = { path = "./tests/common", version = "0.1.0" } 46 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Baptiste de Montangon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![crates.io](https://img.shields.io/crates/v/leptos_i18n.svg)](https://crates.io/crates/leptos_i18n) 2 | 3 | [Docs.rs](https://docs.rs/leptos_i18n/latest/leptos_i18n/) | [Book](https://baptistemontan.github.io/leptos_i18n) 4 | 5 | # Leptos i18n 6 | 7 | This crate is made to simplify internationalization in a [Leptos](https://crates.io/crates/leptos) application, that loads locales at **_compile time_** and provides compile time checks for translation keys, interpolation keys and the selected locale. 8 | 9 | The main focus is ease of use with leptos, a typical component using this crate will look like this: 10 | 11 | ```rust 12 | use crate::i18n::*; 13 | use leptos::prelude::*; 14 | 15 | #[component] 16 | fn Counter() -> impl IntoView { 17 | let i18n = use_i18n(); 18 | 19 | let (counter, set_counter) = signal(0); 20 | let inc = move |_| set_counter.update(|count| *count += 1); 21 | 22 | 23 | view! { 24 | 27 |

28 | {t!(i18n, click_count, count = move || counter.get())} 29 |

30 | } 31 | } 32 | ``` 33 | 34 | ## Getting started 35 | 36 | You can add the crate to your project with 37 | 38 | ```bash 39 | cargo add leptos_i18n 40 | ``` 41 | 42 | Or by adding this line to your `Cargo.toml` under `[dependencies]`: 43 | 44 | ```toml 45 | leptos_i18n = "0.5" 46 | ``` 47 | 48 | ## Version compatibility with leptos 49 | 50 | | Leptos | Leptos i18n | 51 | | ---------- | ------------------- | 52 | | `< v0.4.x` | not supported | 53 | | `v0.4.x` | `v0.1.x` | 54 | | `v0.5.x` | `v0.2.x` | 55 | | `v0.6.x` | `v0.3.x` / `v0.4.x` | 56 | | `v0.7.x` | `v0.5.x` | 57 | 58 | ## How to use 59 | 60 | You can look into the [Book](https://baptistemontan.github.io/leptos_i18n) for documentation, or look for [examples](https://github.com/Baptistemontan/leptos_i18n/tree/master/examples) on the github repo. 61 | -------------------------------------------------------------------------------- /docs/book/.gitignore: -------------------------------------------------------------------------------- 1 | book -------------------------------------------------------------------------------- /docs/book/README.md: -------------------------------------------------------------------------------- 1 | This book is a documentation on how to setup and use the `leptos_i18` lib. 2 | 3 | It is built using `mdbook`. You can view a local copy by installing `mdbook` 4 | 5 | ```bash 6 | cargo install mdbook 7 | ``` 8 | 9 | and run the book with 10 | 11 | ``` 12 | mdbook serve 13 | ``` 14 | 15 | It should be available at `http://localhost:3000`. 16 | -------------------------------------------------------------------------------- /docs/book/src/01_introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | This book is intended as an introduction to the [Leptos_i18n](https://github.com/Baptistemontan/leptos_i18n) crate. 4 | 5 | This crate is made to simplify Internationalization in a [Leptos](https://crates.io/crates/leptos) application that loads locales at **_compile time_** and provides compile-time checks for translation keys, interpolation keys, and the selected locale. 6 | 7 | This guide does assume you know some basics about `Leptos`, but the majority of the guide is about declaring the translations and how to use them. You can find the `Leptos` book [here](https://leptos-rs.github.io/leptos/). 8 | 9 | > The source code for the book is available [here](https://github.com/Baptistemontan/leptos_i18n/tree/main/docs/book). PRs for typos or clarification are always welcome. 10 | -------------------------------------------------------------------------------- /docs/book/src/02_getting_started.md: -------------------------------------------------------------------------------- 1 | # Getting started 2 | 3 | First thing we need is a `Leptos` project, you can find documentation on how to set one up in the `Leptos` [book](https://leptos-rs.github.io/leptos/02_getting_started.html). 4 | 5 | Once you have set one up, you can add this crate to your project with 6 | 7 | ```bash 8 | cargo add leptos_i18n 9 | ``` 10 | 11 | Or by adding this line to your `Cargo.toml` under `[dependencies]`: 12 | 13 | ```toml 14 | leptos_i18n = "0.4" 15 | ``` 16 | 17 | ## `actix-web` Backend 18 | 19 | When compiling for the backend using `actix-web`, enable the `actix` feature: 20 | 21 | ```toml 22 | # Cargo.toml 23 | 24 | [features] 25 | ssr = [ 26 | "leptos_i18n/actix", 27 | ] 28 | ``` 29 | 30 | ## `axum` Backend 31 | 32 | When compiling for the backend using `axum`, enable the `axum` feature: 33 | 34 | ```toml 35 | # Cargo.toml 36 | 37 | [features] 38 | ssr = [ 39 | "leptos_i18n/axum", 40 | ] 41 | ``` 42 | 43 | ## Hydrate 44 | 45 | When compiling for the client, enable the `hydrate` feature: 46 | 47 | ```toml 48 | # Cargo.toml 49 | 50 | [features] 51 | hydrate = [ 52 | "leptos_i18n/hydrate", 53 | ] 54 | ``` 55 | 56 | ## Client Side Rendering 57 | 58 | When compiling for the client, enable the `csr` feature: 59 | 60 | ```toml 61 | # Cargo.toml 62 | 63 | [dependencies.leptos_i18n] 64 | features = ["csr"] 65 | ``` 66 | 67 | You can find examples using CSR on the [github repo](https://github.com/Baptistemontan/leptos_i18n/tree/master/examples/csr) 68 | -------------------------------------------------------------------------------- /docs/book/src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [Introduction](./01_introduction.md) 4 | - [Getting Started](./02_getting_started.md) 5 | - [Setting Up](./setting_up/README.md) 6 | - [Configuration](./setting_up/01_configuration.md) 7 | - [File structure](./setting_up/02_file_structure.md) 8 | - [Namespaces](./setting_up/03_namespaces.md) 9 | - [Inheritance](./setting_up/04_inheritance.md) 10 | - [Declare Translations](./declare/README.md) 11 | - [Key-Value Pairs](./declare/01_key_value.md) 12 | - [Interpolation](./declare/02_interpolation.md) 13 | - [Plurals](./declare/03_plurals.md) 14 | - [Ranges](./declare/04_ranges.md) 15 | - [Subkeys](./declare/05_subkeys.md) 16 | - [Foreign keys](./declare/06_foreign_keys.md) 17 | - [Mixing Kinds](./declare/07_mix_kinds.md) 18 | - [Formatters](./declare/08_formatters.md) 19 | - [Use Translations](./usage/README.md) 20 | - [Load The Translations](./usage/01_load.md) 21 | - [`I18nContext`](./usage/02_context.md) 22 | - [Sub-context](./usage/03_subcontext.md) 23 | - [`t!` Macro](./usage/04_t_macro.md) 24 | - [`td!` Macro](./usage/05_td_macro.md) 25 | - [`td_string!` Macro](./usage/06_td_string_macro.md) 26 | - [`I18nRoute`](./usage/07_router.md) 27 | - [Scoping](./usage/08_scoping.md) 28 | - [`t_format!`](./usage/09_t_format.md) 29 | - [`t_plural!`](./usage/10_t_plural.md) 30 | - [Constant Access](./usage/11_const_access.md) 31 | - [Server functions](./usage/12_serverfn.md) 32 | - [More Informations](./infos/README.md) 33 | - [Locale Resolution](./infos/01_locale_resol.md) 34 | - [Reduce Binary Size](./reduce_size/README.md) 35 | - [ICU4X Datagen](./reduce_size/01_datagen.md) 36 | - [Lazy Load The Translations](./reduce_size/02_dynamic_load.md) 37 | - [Features](./06_features.md) 38 | - [Appendix: `i18n Ally` extension for VSC](./appendix_i18n_ally.md) 39 | -------------------------------------------------------------------------------- /docs/book/src/declare/01_key_value.md: -------------------------------------------------------------------------------- 1 | # Key-Value Pairs 2 | 3 | As expected, you declare your translations as key-value pairs: 4 | 5 | ```json 6 | { 7 | "hello_world": "Hello World!" 8 | } 9 | ``` 10 | 11 | But there are additional rules you must follow in addition to those of the format you use. 12 | 13 | ## Keys 14 | 15 | Key names must be [valid Rust identifiers](https://doc.rust-lang.org/reference/identifiers.html), with the exception of `-` that would be converted to `_`, and does not support [strict](https://doc.rust-lang.org/reference/keywords.html#strict-keywords) or [reserved](https://doc.rust-lang.org/reference/keywords.html#reserved-keywords) keywords. 16 | 17 | ## Same keys across files 18 | 19 | The keys must be the same across all files, else the `load_locales!` macro will emit warnings. The difference in keys is based on the default locale. 20 | 21 | ### Missing key 22 | 23 | If a key is present in the default locale but not in another locale, the other locale will default its value to the default locale one and emit a warning that a key is missing in that locale. 24 | 25 | If you want to explicitly state that this value takes the value of the default locale, you can declare it as `null`: 26 | 27 | ```json 28 | { 29 | "take_value_of_default": null 30 | } 31 | ``` 32 | 33 | This will no longer trigger a warning for that key. 34 | 35 | ### Surplus key 36 | 37 | If a key is present in another locale but not in the default locale, this key will be ignored and a warning will be emitted. 38 | 39 | ## Value Kinds 40 | 41 | You can specify multiple kinds of values: 42 | 43 | - Literals (String, Numbers, Boolean) 44 | - Interpolated String 45 | - Ranges 46 | - Plurals 47 | 48 | The next chapters of this section will cover them, apart from literals, those are self-explanatory. 49 | -------------------------------------------------------------------------------- /docs/book/src/declare/02_interpolation.md: -------------------------------------------------------------------------------- 1 | # Interpolation 2 | 3 | ## Interpolate Values 4 | 5 | There may be situations where you must interpolate a value inside your translations, for example, a dynamic number. 6 | You could declare 2 translations and use them with that number, but this is not an elegant solution. 7 | 8 | To declare a value that will be interpolated in your translations, simply give it a name surrounded by `{{ }}`: 9 | 10 | ```json 11 | { 12 | "click_count": "You clicked {{ count }} times" 13 | } 14 | ``` 15 | 16 | ## Interpolate Components 17 | 18 | There may also be situations where you want to wrap part of your translation into a component, for example, to highlight it. 19 | 20 | You can declare a component with HTML-like syntax: 21 | 22 | ```json 23 | { 24 | "highlight_me": "highlight me" 25 | } 26 | ``` 27 | 28 | ## Use both 29 | 30 | You can mix them both without a problem: 31 | 32 | ```json 33 | { 34 | "click_count": "You clicked {{ count }} times" 35 | } 36 | ``` 37 | 38 | ## Values Names. 39 | 40 | Values names must follow the same rules as [keys](./01_key_value.md#keys). 41 | -------------------------------------------------------------------------------- /docs/book/src/declare/05_subkeys.md: -------------------------------------------------------------------------------- 1 | # Subkeys 2 | 3 | You can declare subkeys by just giving a map to the key: 4 | 5 | ```json 6 | { 7 | "subkeys": { 8 | "subkey_1": "This is subkey_1", 9 | "subkey_n": "This is subkey {{ n }}", 10 | "nested_subkeys": { 11 | "nested_subkey_1": "you can nest subkeys" 12 | } 13 | } 14 | } 15 | ``` 16 | 17 | ```rust,ignore 18 | t!(i18n, subkeys.subkey_1); // -> "This is subkey_1" 19 | t!(i18n, subkeys.nested_subkeys.nested_subkey_1) // -> "you can nest subkeys" 20 | ``` 21 | -------------------------------------------------------------------------------- /docs/book/src/declare/07_mix_kinds.md: -------------------------------------------------------------------------------- 1 | # Mixing Kinds 2 | 3 | What happens if for a key you declare ranges in one locale, interpolation in another, and a simple string in a third ? 4 | 5 | Well, this is totally allowed, but you will still need to supply all values/components of every locale combined when using the translation, regardless of what the current locale is. 6 | 7 | What is not allowed to mix are subkeys. If a key has subkeys in one locale, the key must have subkeys in all locales. 8 | -------------------------------------------------------------------------------- /docs/book/src/declare/README.md: -------------------------------------------------------------------------------- 1 | # Declare translations 2 | 3 | Now that we covered the configuration and where to put each file, we can now start writing the translations. 4 | This chapter covers this topic only for the `JSON` format. 5 | -------------------------------------------------------------------------------- /docs/book/src/infos/01_locale_resol.md: -------------------------------------------------------------------------------- 1 | # Locale Resolution 2 | 3 | This library handles the detection of what locale to use for you, but it can be done in a multitude of ways. 4 | 5 | Here is the list of detection methods, sorted in priorities: 6 | 7 | 1. A locale prefix is present in the URL pathname when using `I18nRoute` (e.g. `/en/about`) 8 | 1. A cookie is present that contains a previously detected locale 9 | 1. A locale can be matched based on the [`Accept-Language` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language) in SSR 10 | 1. A locale can be matched based on the [`navigator.languages` API](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages) in CSR 11 | 1. As a last resort, the default locale is used. 12 | 13 | In SSR, it is always the server that resolves what locale to use; the client does not try to compute a locale when loading; the only locale changes that can happen are by explicitly setting it in the context. 14 | 15 | _note_: URL pathname locale has a behavior that can be unexpected, it only resolve when the `I18nRoute` component start rendering, so if anything relied on the resolved locale before it, 16 | it may have used a different locale than what it should. You can learn more on the [caveat section of the router chapter](../usage/07_router.md#caveat). 17 | -------------------------------------------------------------------------------- /docs/book/src/infos/README.md: -------------------------------------------------------------------------------- 1 | # More Information 2 | 3 | This chapter covers more information that details some behavior that is expected, such as how the locale resolution is done. 4 | -------------------------------------------------------------------------------- /docs/book/src/reduce_size/README.md: -------------------------------------------------------------------------------- 1 | # How To Reduce Binary Size 2 | 3 | This chapter is about the few options you have to reduce the binary footprint of this library, other than compiler options such as `opt-level = "z"` and other things that are common for every build. 4 | -------------------------------------------------------------------------------- /docs/book/src/setting_up/01_configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | This crate is basically entirely based around one macro: the `load_locales!` macro. We will cover it in a later chapter, but for now just know that it looks at your translation files and generates code for them. 4 | 5 | To load those translations it first needs to know what to look for, so you need to declare what locales you are supporting and which one is the default. 6 | To do that you use the `[package.metadata.leptos-i18n]` section in your `Cargo.toml`. 7 | 8 | To declare `en` and `fr` as locales, with `en` being the default you would write: 9 | 10 | ```toml 11 | [package.metadata.leptos-i18n] 12 | default = "en" 13 | locales = ["en", "fr"] 14 | ``` 15 | 16 | There are more optional values you can supply: 17 | 18 | - `namespaces`: This is to split your translations into multiple files, we will cover it in a later chapter 19 | - `locales-dir`: This is to have a custom path to the directory containing the locales files, it defaults to `"./locales"`. 20 | - `translations-path`: Used in a CSR application with the `dynamic_load` feature, more information in a later chapter. 21 | - `inherits`: Allow to describe inheritance structure for locales, covered in a later chapter. 22 | 23 | Once this configuration is done, you can start writing your translations. 24 | -------------------------------------------------------------------------------- /docs/book/src/setting_up/02_file_structure.md: -------------------------------------------------------------------------------- 1 | # File Structure 2 | 3 | Now that you have configured your locales, you can start writing your translations. This chapter covers where to put your files. We will cover how to write them in another section. 4 | 5 | By default, you must put your files in the `./locales` directory, and each file must be `%{locale}.json`: 6 | 7 | ```bash 8 | ./locales 9 | ├── en.json 10 | └── fr.json 11 | ``` 12 | 13 | ## Custom Directory 14 | 15 | You can change the path to the directory containing the files with the `locales-dir` field in the configuration, for example: 16 | 17 | ```toml 18 | [package.metadata.leptos-i18n] 19 | default = "en" 20 | locales = ["en", "fr"] 21 | locales-dir = "./path/to/mylocales” 22 | ``` 23 | 24 | will look for: 25 | 26 | ```bash 27 | ./path 28 | └── to 29 | └── mylocales 30 | ├── en.json 31 | └── fr.json 32 | ``` 33 | 34 | ## Other Formats 35 | 36 | JSON being the default, you can change that by first removing the default features and enabling the feature for the format you need: 37 | 38 | ```toml 39 | # Cargo.toml 40 | 41 | [dependencies] 42 | leptos_i18n = { 43 | default-features = false, 44 | features = ["yaml_files"] 45 | } 46 | ``` 47 | 48 | | Format | Feature | 49 | | -------------- | ------------ | 50 | | JSON (default) | `json_files` | 51 | | YAML | `yaml_files` | 52 | 53 | Other formats may be supported later. 54 | -------------------------------------------------------------------------------- /docs/book/src/setting_up/03_namespaces.md: -------------------------------------------------------------------------------- 1 | # Namespaces 2 | 3 | Translations files can grow quite rapidly and become very big, and avoiding key collisions can be hard without avoiding long names. 4 | To avoid this situation, you can declare namespaces in the configuration: 5 | 6 | ```toml 7 | [package.metadata.leptos-i18n] 8 | default = "en" 9 | locales = ["en", "fr"] 10 | namespaces = ["common", "home"] 11 | ``` 12 | 13 | Then your file structures must look like this in the `/locales` directory: 14 | 15 | ```bash 16 | ./locales 17 | ├── en 18 | │   ├── common.json 19 | │   └── home.json 20 | └── fr 21 | ├── common.json 22 | └── home.json 23 | ``` 24 | 25 | You can now make smaller files, with one for each section of the website, for example. 26 | This also allows the `common` namespace to use keys that the `home` namespace also uses, without colliding. 27 | -------------------------------------------------------------------------------- /docs/book/src/setting_up/04_inheritance.md: -------------------------------------------------------------------------------- 1 | # Extanding a locale 2 | 3 | The `inherits` config options under the `[package.metadata.leptos-i18n]` can allow you to describe inheritance hierarchy for your locales: 4 | 5 | ```toml 6 | [package.metadata.leptos-i18n] 7 | default = "en" 8 | locales = ["en", "fr", "fr-CA"] 9 | inherits = { fr-CA = "fr" } 10 | ``` 11 | 12 | This will default any missing keys in "fr-CA" to the value in "fr". 13 | 14 | The "general" default for missing keys will still be the default locale, so if a key is missing in both "fr" and "fr-CA", the key will use the value in "en". 15 | 16 | ## Recursive inheritance 17 | 18 | You can have recursive inheritances, this is allowed and works as expected: 19 | 20 | ```toml 21 | [package.metadata.leptos-i18n] 22 | default = "en" 23 | locales = ["en", "fr", "fr-CA", "fr-FR"] 24 | inherits = { fr-CA = "fr-FR", fr-FR = "fr" } 25 | ``` 26 | 27 | > note: cyclic inheritance is also valid but I don't see the use, it's only supported because if we didn't detected cycles we could have an endless loop when resolving what default to use, if a cycle is encountered on a missing key the default locale is used. 28 | 29 | ## Missing key warnings 30 | 31 | if locale A extend locale B, missing key warnings will not be emitted for locale A. 32 | 33 | Explicitly setting the inheritance to the default locale is also a way to suppress missing key warnings for a given locale: 34 | 35 | ```toml 36 | [package.metadata.leptos-i18n] 37 | default = "en" 38 | locales = ["en", "fr", "it"] 39 | inherits = { it = "en" } 40 | ``` 41 | 42 | While the above is technically already the default behavior, missing warnings will not be emitted for the "it" locale, but will be emitted for the "fr" locale. 43 | 44 | ## Extends the default locale 45 | 46 | The default locale can not inherit. 47 | 48 | This is not allowed and will error: 49 | 50 | ```toml 51 | [package.metadata.leptos-i18n] 52 | default = "en" 53 | locales = ["en", "fr"] 54 | inherits = { en = "fr" } 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/book/src/setting_up/README.md: -------------------------------------------------------------------------------- 1 | # Setting Up 2 | 3 | This first section will introduce you to the configuration you need to use `leptos_i18n`. By the end of this section, you should be able to 4 | set up the basics to start using translations in your `Leptos` application. 5 | -------------------------------------------------------------------------------- /docs/book/src/usage/05_td_macro.md: -------------------------------------------------------------------------------- 1 | # The `td!` Macro 2 | 3 | The `td!` macro works just like the `t!` macro but instead of taking the context as its first argument, it takes the desired locale: 4 | 5 | ```rust,ignore 6 | td!(Locale::fr, hello_world) 7 | ``` 8 | 9 | This is useful if, for example, you want the buttons to switch locale to always be in the language they switch to: 10 | 11 | ```rust,ignore 12 | use crate::i18n::*; 13 | use leptos::prelude::*; 14 | 15 | #[component] 16 | pub fn Foo() -> impl IntoView { 17 | let i18n = use_i18n(); 18 | 19 | view! { 20 | 25 | 28 | 29 | } 30 | } 31 | ``` 32 | 33 | This could just be written as 34 | 35 | ```rust,ignore 36 | use crate::i18n::*; 37 | use leptos::prelude::*; 38 | 39 | #[component] 40 | pub fn Foo() -> impl IntoView { 41 | let i18n = use_i18n(); 42 | 43 | view! { 44 | 47 | 50 | } 51 | } 52 | ``` 53 | 54 | But the above scale is better. 55 | -------------------------------------------------------------------------------- /docs/book/src/usage/09_t_format.md: -------------------------------------------------------------------------------- 1 | # `t_format!` 2 | 3 | You may want to use the formatting capability without the need to create an entry in your translations; you can use the `t_format!` macro for that: 4 | 5 | ```rust,ignore 6 | use crate::i18n::*; 7 | use leptos_i18n::formatting::t_format; 8 | 9 | let i18n = use_i18n(); 10 | 11 | let num = move || 100_000; 12 | 13 | t_format!(i18n, num, formatter: number); 14 | ``` 15 | 16 | There are 9 variants, just like the `t!` macro, `td_format!`, `tu_format!`, `*_format_string`, and `*_format_display`. 17 | 18 | ### Example 19 | 20 | ```rust,ignore 21 | let date = move || Date::try_new_iso_date(1970, 1, 2).unwrap().to_any(); 22 | 23 | let en = td_format_string!(Locale::en, date, formatter: date); 24 | assert_eq!(en, "Jan 2, 1970"); 25 | let fr = td_format_string!(Locale::fr, date, formatter: date(date_length: full)); 26 | assert_eq!(fr, "vendredi 2 janvier 1970"); 27 | 28 | 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/book/src/usage/10_t_plural.md: -------------------------------------------------------------------------------- 1 | # `t_plural!` 2 | 3 | You can use the `t_plural!` macro to match on the plural form of a given count: 4 | 5 | ```rust,ignore 6 | let i18n = use_i18n(); 7 | 8 | let form = t_plural! { 9 | i18n, 10 | count = || 0, 11 | one => "one", 12 | _ => "other" 13 | }; 14 | 15 | Effect::new(|| { 16 | let s = form(); 17 | log!("{}", s); 18 | }) 19 | ``` 20 | 21 | This will print "one" with locale "fr" but "other" with locale "en". 22 | Accepted forms are: `zero`, `one`, `two`, `few`, `many`, `other`, and `_`. 23 | 24 | This macro is for cardinal plurals; if you want to match against ordinal plurals, use the `t_plural_ordinal!` macro. 25 | -------------------------------------------------------------------------------- /docs/book/src/usage/11_const_access.md: -------------------------------------------------------------------------------- 1 | # Access translations in a const context 2 | 3 | You can access the translations in a const context if you have those things: 4 | 5 | - Constant Locale 6 | - No arguments 7 | - No using the "dynamic_load" feature 8 | 9 | If you have 10 | 11 | ```json 12 | { 13 | "subkeys:": { 14 | "key": "my value" 15 | } 16 | } 17 | ``` 18 | 19 | You can do 20 | 21 | ```rust,ignore 22 | use crate::i18n::*; 23 | const MY_VALUE: &str = Locale::en.get_keys_const().subkeys().key().inner(); 24 | ``` 25 | 26 | If you want a macro: 27 | 28 | ```rust,ignore 29 | macro_rules! td_const { 30 | ($locale:expr, $first_key:ident $(.$key:ident)*) => { 31 | ($locale).get_keys_const() 32 | .$first_key() 33 | $(.$key())* 34 | .inner() 35 | }; 36 | } 37 | 38 | const MY_VALUE: &str = td_const(Locale::en, subkeys.key); 39 | 40 | 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/book/src/usage/12_serverfn.md: -------------------------------------------------------------------------------- 1 | # Server functions 2 | 3 | There is no context in server functions, so you can't call `use_i18n`. You could provide a context if you want, 4 | and it would work as expected, but if you just want to access what locale the user is using you can use the `resolve_locale` function: 5 | 6 | ```rust 7 | #[server] 8 | async fn get_locale() -> Result { 9 | let locale: Locale = leptos_i18n::locale::resolve_locale(); 10 | Ok(locale) 11 | } 12 | ``` 13 | -------------------------------------------------------------------------------- /docs/book/src/usage/README.md: -------------------------------------------------------------------------------- 1 | # How to use in code 2 | 3 | Now that we know how to declare our translations, we can incorporate them into the code, and this is what this chapter covers. 4 | -------------------------------------------------------------------------------- /docs/expanded_macros/scope.md: -------------------------------------------------------------------------------- 1 | This document contain what the different scoping macros should expand to. Those macros output the same code whatever the feature flags, so no flags are relevant. 2 | 3 | # `use_i18n_scoped!` 4 | 5 | Code: 6 | 7 | ```rust 8 | let i18n = use_i18n_scoped!($keys); 9 | ``` 10 | 11 | Expanded code: 12 | 13 | ```rust 14 | let i18n = { 15 | leptos_i18n::__private::scope_ctx_util(use_i18n(), |_k| &_k.$keys) 16 | }; 17 | ``` 18 | 19 | # `scope_i18n!` 20 | 21 | Code: 22 | 23 | ```rust 24 | let i18n = scope_i18n!($ctx, $keys); 25 | ``` 26 | 27 | Expanded code: 28 | 29 | ```rust 30 | let i18n = { 31 | leptos_i18n::__private::scope_ctx_util($ctx, |_k| &_k.$keys) 32 | }; 33 | ``` 34 | 35 | Yes. `use_i18n_scoped!($keys)` is just `scope_i18n!(use_i18n(), $keys)`. 36 | 37 | # `scope_locale!` 38 | 39 | Code: 40 | 41 | ```rust 42 | let locale = scope_i18n!($locale, $keys); 43 | ``` 44 | 45 | Expanded code: 46 | 47 | ```rust 48 | let locale = { 49 | leptos_i18n::__private::scope_locale_util($locale, |_k| &_k.$keys) 50 | }; 51 | ``` 52 | -------------------------------------------------------------------------------- /examples/csr/counter/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/counter/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/counter/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/counter/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | leptos = { version = "0.7.0", features = ["csr"] } 10 | leptos_meta = { version = "0.7.0" } 11 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr"] } 12 | serde = { version = "1", features = ["derive"] } 13 | console_error_panic_hook = { version = "0.1" } 14 | wasm-bindgen = { version = "0.2" } 15 | 16 | [package.metadata.leptos-i18n] 17 | default = "en" 18 | locales = ["en", "fr"] 19 | -------------------------------------------------------------------------------- /examples/csr/counter/README.md: -------------------------------------------------------------------------------- 1 | # Counter Example 2 | 3 | This example showcase how you can interpolate a variable in your translations and switch locale without loosing state. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/counter/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count": "You clicked {{ count }} times", 4 | "click_to_inc": "Click to increment the counter" 5 | } -------------------------------------------------------------------------------- /examples/csr/counter/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count": "Vous avez cliqué {{ count }} fois", 4 | "click_to_inc": "Cliquez pour incrémenter le compteur" 5 | } -------------------------------------------------------------------------------- /examples/csr/counter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "counter", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can interpolate a variable in your translations and switch locale without loosing state.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/counter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/counter/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, click_count, count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/csr/counter/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }) 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/counter/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter/style/main.scss -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales", 4 | "rust-analyzer.cargo.buildScripts.enable": true 5 | } -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter_icu_datagen" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | leptos = { version = "0.7.0", features = ["csr"] } 8 | leptos_meta = { version = "0.7.0" } 9 | leptos_i18n = { path = "../../../leptos_i18n", default-features = false, features = [ 10 | "json_files", 11 | "csr", 12 | "plurals", 13 | "format_nums", 14 | "format_list", 15 | "format_datetime", 16 | # experimental feature 17 | "format_currency", 18 | ] } 19 | serde = { version = "1", features = ["derive"] } 20 | console_error_panic_hook = { version = "0.1" } 21 | wasm-bindgen = { version = "0.2" } 22 | 23 | # "default-features = false" to turn off compiled_data 24 | icu = { version = "1.5", default-features = false, features = [ 25 | # feature only needed for experimental features (e.g "format_currency") 26 | "experimental", 27 | ] } 28 | icu_provider = "1.5" # for databake 29 | zerovec = "0.10" # for databake 30 | 31 | # only needed for experimental features (e.g "format_currency") 32 | icu_pattern = "0.2.0" # for databake 33 | 34 | [package.metadata.leptos-i18n] 35 | default = "en" 36 | locales = ["en", "fr"] 37 | 38 | [build-dependencies] 39 | leptos_i18n_build = { path = "../../../leptos_i18n_build" } 40 | 41 | [profile.release] 42 | opt-level = "z" 43 | lto = true 44 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/README.md: -------------------------------------------------------------------------------- 1 | # Counter Plurals Example 2 | 3 | This example showcase how you can use plurals to display a different text based on a count. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/build.rs: -------------------------------------------------------------------------------- 1 | use leptos_i18n_build::TranslationsInfos; 2 | use std::path::PathBuf; 3 | 4 | fn main() { 5 | println!("cargo:rerun-if-changed=build.rs"); 6 | println!("cargo:rerun-if-changed=Cargo.toml"); 7 | 8 | let mod_directory = PathBuf::from(std::env::var_os("OUT_DIR").unwrap()).join("baked_data"); 9 | 10 | let translations_infos = TranslationsInfos::parse().unwrap(); 11 | 12 | translations_infos.rerun_if_locales_changed(); 13 | 14 | translations_infos.generate_data(mod_directory).unwrap(); 15 | } 16 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count_one": "You clicked {{ count }} time", 4 | "click_count_other": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter", 6 | "num_formatter": "{{ num, number }}", 7 | "currency_formatter": "{{ num, currency }}", 8 | "date_formatter": "{{ date_var, date }}", 9 | "list_formatter": "{{ list_var, list }}" 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count_one": "Vous avez fait {{ count }} clique", 4 | "click_count_other": "Vous avez fait {{ count }} cliques", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur", 6 | "num_formatter": "{{ num, number }}", 7 | "currency_formatter": "{{ num, currency }}", 8 | "date_formatter": "{{ date_var, date }}", 9 | "list_formatter": "{{ list_var, list }}" 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "counter_ranges", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can use ranges to display a different text based on a count.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter_icu_datagen/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, click_count, count = count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | include!(concat!(env!("OUT_DIR"), "/baked_data/mod.rs")); 7 | 8 | // only needed for experimental features (e.g "format_currency") 9 | extern crate alloc; 10 | 11 | #[derive(leptos_i18n::custom_provider::IcuDataProvider)] 12 | pub struct BakedProvider; 13 | impl_data_provider!(BakedProvider); 14 | 15 | fn main() { 16 | use app::App; 17 | leptos_i18n::custom_provider::set_icu_data_provider(BakedProvider); 18 | console_error_panic_hook::set_once(); 19 | leptos::mount::mount_to_body(|| leptos::view! { }) 20 | } 21 | -------------------------------------------------------------------------------- /examples/csr/counter_icu_datagen/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter_icu_datagen/style/main.scss -------------------------------------------------------------------------------- /examples/csr/counter_plurals/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/counter_plurals/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/counter_plurals/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter_plurals" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | leptos = { version = "0.7.0", features = ["csr"] } 8 | leptos_meta = { version = "0.7.0" } 9 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr", "plurals"] } 10 | serde = { version = "1", features = ["derive"] } 11 | console_error_panic_hook = { version = "0.1" } 12 | wasm-bindgen = { version = "0.2" } 13 | 14 | [package.metadata.leptos-i18n] 15 | default = "en" 16 | locales = ["en", "fr"] 17 | 18 | [profile.release] 19 | opt-level = "z" 20 | lto = true 21 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/README.md: -------------------------------------------------------------------------------- 1 | # Counter Plurals Example 2 | 3 | This example showcase how you can use plurals to display a different text based on a count. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count_one": "You clicked {{ count }} time", 4 | "click_count_other": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter" 6 | } 7 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count_one": "Vous avez fait {{ count }} clique", 4 | "click_count_other": "Vous avez fait {{ count }} cliques", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur" 6 | } 7 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "counter_ranges", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can use ranges to display a different text based on a count.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter_plurals/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/counter_plurals/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, click_count, count = count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }) 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/counter_plurals/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter_plurals/style/main.scss -------------------------------------------------------------------------------- /examples/csr/counter_ranges/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/counter_ranges/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/counter_ranges/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "counter_ranges" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | leptos = { version = "0.7.0", features = ["csr"] } 8 | leptos_meta = { version = "0.7.0" } 9 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr"] } 10 | serde = { version = "1", features = ["derive"] } 11 | console_error_panic_hook = { version = "0.1" } 12 | wasm-bindgen = { version = "0.2" } 13 | 14 | [package.metadata.leptos-i18n] 15 | default = "en" 16 | locales = ["en", "fr"] 17 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/README.md: -------------------------------------------------------------------------------- 1 | # Counter Ranges Example 2 | 3 | This example showcase how you can use ranges to display a different text based on a count. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count": [ 4 | ["You have not clicked yet", 0], 5 | ["You clicked once", 1], 6 | ["You clicked {{ count }} times", "2..20"], 7 | ["You clicked a lot", "20.."], 8 | ["You clicked a negative amount ??", "..0"] 9 | ], 10 | "click_to_inc": "Click to increment the counter" 11 | } 12 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count": [ 4 | ["Vous n'avez pas cliqué", "0"], 5 | ["Vous avez cliqué une fois", 1], 6 | ["Vous avez cliqué {{ count }} fois", "2..20"], 7 | ["Vous avez beaucoup cliqué", "20.."], 8 | ["Vous avez cliqué un nombre négatif de fois ??"] 9 | ], 10 | "click_to_inc": "Cliquez pour incrémenter le compteur" 11 | } 12 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "counter_ranges", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can use ranges to display a different text based on a count.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter_ranges/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/counter_ranges/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, click_count, count = count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }) 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/counter_ranges/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/counter_ranges/style/main.scss -------------------------------------------------------------------------------- /examples/csr/interpolation/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/interpolation/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/interpolation/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/interpolation/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/interpolation/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "interpolate" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | leptos = { version = "0.7.0", features = ["csr"] } 10 | leptos_meta = { version = "0.7.0" } 11 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr"] } 12 | serde = { version = "1", features = ["derive"] } 13 | console_error_panic_hook = { version = "0.1" } 14 | wasm-bindgen = { version = "0.2" } 15 | 16 | [package.metadata.leptos-i18n] 17 | default = "en" 18 | locales = ["en", "fr"] 19 | -------------------------------------------------------------------------------- /examples/csr/interpolation/README.md: -------------------------------------------------------------------------------- 1 | # Interpolation Example 2 | 3 | This example showcase how you can interpolate components/variable in your translations. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/interpolation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/interpolation/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count": "You clicked {{ count }} times", 4 | "click_to_inc": "Click to increment the counter" 5 | } -------------------------------------------------------------------------------- /examples/csr/interpolation/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count": "Vous avez cliqué {{ count }} fois", 4 | "click_to_inc": "Cliquez pour incrémenter le compteur" 5 | } -------------------------------------------------------------------------------- /examples/csr/interpolation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "interpolation", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can interpolate components/variable in your translations.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/interpolation/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/interpolation/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/interpolation/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, click_count, count, = )}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/csr/interpolation/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/interpolation/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/interpolation/style/main.scss -------------------------------------------------------------------------------- /examples/csr/namespaces/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/namespaces/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/namespaces/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/namespaces/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales", 4 | "i18n-ally.namespace": true 5 | } -------------------------------------------------------------------------------- /examples/csr/namespaces/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "namespaces" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | leptos = { version = "0.7.0", features = ["csr"] } 10 | leptos_meta = { version = "0.7.0" } 11 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr"] } 12 | serde = { version = "1", features = ["derive"] } 13 | console_error_panic_hook = { version = "0.1" } 14 | wasm-bindgen = { version = "0.2" } 15 | 16 | [package.metadata.leptos-i18n] 17 | default = "en" 18 | locales = ["en", "fr"] 19 | namespaces = ["change_locale", "counter"] 20 | -------------------------------------------------------------------------------- /examples/csr/namespaces/README.md: -------------------------------------------------------------------------------- 1 | # Namespaces Example 2 | 3 | This example showcase how you can break down your translations in separate files using namespaces. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/namespaces/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/namespaces/locales/en/change_locale.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language" 3 | } -------------------------------------------------------------------------------- /examples/csr/namespaces/locales/en/counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_count": "You clicked {{ count }} times", 3 | "click_to_inc": "Click to increment the counter" 4 | } -------------------------------------------------------------------------------- /examples/csr/namespaces/locales/fr/change_locale.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue" 3 | } -------------------------------------------------------------------------------- /examples/csr/namespaces/locales/fr/counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_count": "Vous avez cliqué {{ count }} fois", 3 | "click_to_inc": "Cliquez pour incrémenter le compteur" 4 | } -------------------------------------------------------------------------------- /examples/csr/namespaces/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "namespaces", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can break down your translations in separate files using namespaces.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/namespaces/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/namespaces/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/namespaces/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, counter.click_count, count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/csr/namespaces/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/namespaces/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/namespaces/style/main.scss -------------------------------------------------------------------------------- /examples/csr/routing_csr/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/routing_csr/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/routing_csr/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "routing_csr" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | leptos = { version = "0.7.0", features = ["csr"] } 10 | leptos_meta = { version = "0.7.0" } 11 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr"] } 12 | leptos_i18n_router = { path = "../../../leptos_i18n_router" } 13 | serde = { version = "1", features = ["derive"] } 14 | console_error_panic_hook = { version = "0.1" } 15 | wasm-bindgen = { version = "0.2" } 16 | 17 | leptos_router = { version = "0.7.0" } 18 | 19 | [package.metadata.leptos-i18n] 20 | default = "en" 21 | locales = ["en", "fr"] 22 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/README.md: -------------------------------------------------------------------------------- 1 | # Routing CSR 2 | 3 | This example showcase how to setup the router using `leptos_i18n` in a CSR project. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language", 4 | "click_count": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter", 6 | "go_home": "Homepage", 7 | "go_counter": "Counter" 8 | } 9 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue", 4 | "click_count": "Vous avez cliqué {{ count }} fois", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur", 6 | "go_home": "Accueil", 7 | "go_counter": "Compteur" 8 | } 9 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "routing_csr", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to use routing with CSR", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/routing_csr/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/routing_csr/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }) 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/routing_csr/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/routing_csr/style/main.scss -------------------------------------------------------------------------------- /examples/csr/subcontext/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/subcontext/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/subcontext/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/subcontext/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/subcontext/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "subcontext" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | leptos = { version = "0.7.0", features = ["csr"] } 10 | leptos_meta = { version = "0.7.0" } 11 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr"] } 12 | serde = { version = "1", features = ["derive"] } 13 | console_error_panic_hook = { version = "0.1" } 14 | wasm-bindgen = { version = "0.2" } 15 | 16 | [package.metadata.leptos-i18n] 17 | default = "en" 18 | locales = ["en", "fr"] 19 | -------------------------------------------------------------------------------- /examples/csr/subcontext/README.md: -------------------------------------------------------------------------------- 1 | # Counter Example 2 | 3 | This example showcase how you can use subcontexts in you application. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/subcontext/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/subcontext/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count": "You clicked {{ count }} times", 4 | "click_to_inc": "Click to increment the counter", 5 | "examples": { 6 | "opposite": "This section takes the opposite locale to the parent context when the later changes.", 7 | "cookie": "This section start with it's own default locale and saves it in a cookie.", 8 | "lang_attr": "This section update the \"lang\" HTML attribute of the parent div.", 9 | "all": "This section is reversed, has a cookie, and update the \"lang\" attribute.", 10 | "main": "This section follows the main context." 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/csr/subcontext/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count": "Vous avez cliqué {{ count }} fois", 4 | "click_to_inc": "Cliquez pour incrémenter le compteur", 5 | "examples": { 6 | "opposite": "Cette section prendra la locale opposée à celle du context parent lorsque celle ci change.", 7 | "cookie": "Cette section commence avec sa propre locale par défaut et sauvegarde les changements dans un cookie.", 8 | "lang_attr": "Cette section maintient à jour l'attribut HTML \"lang\" de l'élément
parent.", 9 | "all": "Cette section est inversé, a son cookie, et met l'attribut \"lang\".", 10 | "main": "Ce compteur utilise le context principal." 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/csr/subcontext/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subcontext", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can introduce subcontexts in you application.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/subcontext/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/subcontext/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/subcontext/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }) 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/subcontext/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/subcontext/style/main.scss -------------------------------------------------------------------------------- /examples/csr/subkeys/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/subkeys/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/subkeys/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/subkeys/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/subkeys/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "subkeys" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | leptos = { version = "0.7.0", features = ["csr"] } 10 | leptos_meta = { version = "0.7.0" } 11 | leptos_i18n = { path = "../../../leptos_i18n", features = ["csr"] } 12 | serde = { version = "1", features = ["derive"] } 13 | console_error_panic_hook = { version = "0.1" } 14 | wasm-bindgen = { version = "0.2" } 15 | 16 | [package.metadata.leptos-i18n] 17 | default = "en" 18 | locales = ["en", "fr"] 19 | -------------------------------------------------------------------------------- /examples/csr/subkeys/README.md: -------------------------------------------------------------------------------- 1 | # Subkeys Example 2 | 3 | This example showcase how you can use subkeys. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/subkeys/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/subkeys/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "subkeys": { 4 | "subkey": "subkeys subkey english", 5 | "subsubkeys": { 6 | "subsubkey": "subkeys subsubkeys subsubkey english" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/csr/subkeys/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "subkeys": { 4 | "subkey": "subkeys subkey french", 5 | "subsubkeys": { 6 | "subsubkey": "subkeys subsubkeys subsubkey french" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/csr/subkeys/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "subkeys", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can use subkeys.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/csr/subkeys/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/subkeys/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/subkeys/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Subkeys() -> impl IntoView { 38 | let i18n = use_i18n_scoped!(subkeys); 39 | 40 | view! { 41 |

{t!(i18n, subkey)}

42 |

{t!(i18n, subsubkeys.subsubkey)}

43 | } 44 | } 45 | -------------------------------------------------------------------------------- /examples/csr/subkeys/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/subkeys/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/subkeys/style/main.scss -------------------------------------------------------------------------------- /examples/csr/yaml/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/csr/yaml/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/csr/yaml/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/csr/yaml/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/csr/yaml/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "yaml" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | leptos = { version = "0.7.0", features = ["csr"] } 10 | leptos_meta = { version = "0.7.0" } 11 | leptos_i18n = { path = "../../../leptos_i18n", default-features = false, features = [ 12 | "csr", 13 | "cookie", 14 | "yaml_files", 15 | "icu_compiled_data", 16 | ] } 17 | serde = { version = "1", features = ["derive"] } 18 | console_error_panic_hook = { version = "0.1" } 19 | wasm-bindgen = { version = "0.2" } 20 | 21 | [package.metadata.leptos-i18n] 22 | default = "en" 23 | locales = ["en", "fr"] 24 | -------------------------------------------------------------------------------- /examples/csr/yaml/README.md: -------------------------------------------------------------------------------- 1 | # YAML Example 2 | 3 | This example showcase how you can use the YAML format for declaring your locales 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/csr/yaml/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /examples/csr/yaml/locales/en.yaml: -------------------------------------------------------------------------------- 1 | click_to_change_lang: "Click to change language" 2 | click_to_inc: "Click to increment the counter" 3 | click_count: 4 | - "u64" 5 | - ["You did not clicked yet", 0] 6 | - ["You clicked once", 1] 7 | - ["You clicked {{ count }} times"] 8 | subkeys: 9 | subkey: "subkey" 10 | sub_subkeys: 11 | sub_sbkey: "sub_subkey" 12 | -------------------------------------------------------------------------------- /examples/csr/yaml/locales/fr.yaml: -------------------------------------------------------------------------------- 1 | click_to_change_lang: "Cliquez pour changez de langue" 2 | click_count: "Vous avez cliqué {{ count }} fois" 3 | click_to_inc: "Cliquez pour incrémenter le compteur" 4 | subkeys: 5 | subkey: "subkey fr" 6 | sub_subkeys: 7 | sub_sbkey: "sub_subkey fr" 8 | -------------------------------------------------------------------------------- /examples/csr/yaml/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "yaml", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can use the YAML format for declaring your locales", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12", 20 | "yaml": "^2.5.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /examples/csr/yaml/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/yaml/public/favicon.ico -------------------------------------------------------------------------------- /examples/csr/yaml/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0u64); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, click_count, count = count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/csr/yaml/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }); 10 | } 11 | -------------------------------------------------------------------------------- /examples/csr/yaml/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/csr/yaml/style/main.scss -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/README.md: -------------------------------------------------------------------------------- 1 | # Hello World Example 2 | 3 | This example showcase how to use `leptos_i18n` with experimental `island` feature from Leptos. 4 | 5 | ## How to run 6 | 7 | Simply use `cargo_leptos` to run it: 8 | 9 | ```sh 10 | cargo leptos watch 11 | ``` 12 | 13 | and to build: 14 | 15 | ```sh 16 | cargo leptos build --release 17 | ``` 18 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language", 4 | "click_count": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter" 6 | } 7 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue", 4 | "click_count": "Vous avez cliqué {{ count }} fois", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur" 6 | } 7 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "axum_island", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to use `leptos_i18n` with experimental `island` feature from Leptos.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/axum_island/public/favicon.ico -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | view! { 8 | 9 |

10 | {ti!(HelloWorld, hello_world)} 11 |

12 | 13 | 14 |
15 | } 16 | } 17 | 18 | #[island] 19 | #[allow(non_snake_case)] 20 | fn Counter() -> impl IntoView { 21 | let i18n = use_i18n(); 22 | 23 | let (counter, set_counter) = signal(0); 24 | 25 | let inc = move |_| set_counter.update(|count| *count += 1); 26 | 27 | let count = move || counter.get(); 28 | 29 | view! { 30 |

31 | {t!{ 32 | i18n, 33 | click_count, 34 | count, 35 | = , 36 | }} 37 |

38 | 39 | } 40 | } 41 | 42 | #[island] 43 | #[allow(non_snake_case)] 44 | fn ChangeLang() -> impl IntoView { 45 | let i18n = use_i18n(); 46 | 47 | let on_switch = move |_| { 48 | let new_lang = match i18n.get_locale() { 49 | Locale::en => Locale::fr, 50 | Locale::fr => Locale::en, 51 | }; 52 | i18n.set_locale(new_lang); 53 | }; 54 | 55 | view! { 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | 5 | leptos_i18n::load_locales!(); 6 | 7 | #[cfg(feature = "hydrate")] 8 | #[wasm_bindgen::prelude::wasm_bindgen] 9 | pub fn hydrate() { 10 | console_error_panic_hook::set_once(); 11 | leptos::mount::hydrate_islands(); 12 | } 13 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::Router; 2 | use axum_island::app::App; 3 | use leptos::prelude::*; 4 | use leptos_axum::{generate_route_list, LeptosRoutes}; 5 | 6 | #[tokio::main] 7 | async fn main() { 8 | // Setting this to None means we'll be using cargo-leptos and its env vars 9 | let conf = get_configuration(None).unwrap(); 10 | let leptos_options = conf.leptos_options; 11 | let addr = leptos_options.site_addr; 12 | let routes = generate_route_list(App); 13 | 14 | // build our application with a route 15 | let app = Router::new() 16 | .leptos_routes(&leptos_options, routes, { 17 | let leptos_options = leptos_options.clone(); 18 | move || shell(leptos_options.clone()) 19 | }) 20 | .fallback(leptos_axum::file_and_error_handler(shell)) 21 | .with_state(leptos_options); 22 | 23 | // run our app with hyper 24 | // `axum::Server` is a re-export of `hyper::Server` 25 | let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); 26 | println!("listening on http://{}", &addr); 27 | axum::serve(listener, app.into_make_service()) 28 | .await 29 | .unwrap(); 30 | } 31 | 32 | pub fn shell(options: LeptosOptions) -> impl IntoView { 33 | view! { 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/dynamic_load/axum_island/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/axum_island/style/main.scss -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | dist 4 | !.vscode 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ 10 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales", 4 | "rust-analyzer.cargo.buildScripts.enable": true 5 | } -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "csr_counter" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | leptos = { version = "0.7.0", features = ["csr"] } 8 | leptos_i18n = { path = "../../../leptos_i18n", features = [ 9 | "csr", 10 | "plurals", 11 | "dynamic_load", 12 | "track_locale_files", 13 | ] } 14 | console_error_panic_hook = { version = "0.1" } 15 | 16 | [package.metadata.leptos-i18n] 17 | default = "en" 18 | locales = ["en", "fr"] 19 | translations-path = "i18n/{locale}.json" 20 | 21 | [build-dependencies] 22 | leptos_i18n_build = { path = "../../../leptos_i18n_build" } 23 | 24 | [profile.release] 25 | opt-level = "z" 26 | lto = true 27 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/README.md: -------------------------------------------------------------------------------- 1 | # Dynamic Load CSR Counter Example 2 | 3 | This example showcase how you can use dynamic load with CSR. 4 | 5 | ## How to run 6 | 7 | Simply use `trunk` to run it: 8 | 9 | ```bash 10 | trunk serve --open 11 | ``` 12 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/build.rs: -------------------------------------------------------------------------------- 1 | use leptos_i18n_build::TranslationsInfos; 2 | 3 | fn main() { 4 | println!("cargo:rerun-if-changed=build.rs"); 5 | println!("cargo:rerun-if-changed=Cargo.toml"); 6 | 7 | let translations_infos = TranslationsInfos::parse().unwrap(); 8 | 9 | translations_infos.rerun_if_locales_changed(); 10 | 11 | translations_infos 12 | .get_translations() 13 | .write_to_dir("./target/i18n") 14 | .unwrap(); 15 | } 16 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count_one": "You clicked {{ count }} time", 4 | "click_count_other": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter" 6 | } 7 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count_one": "Vous avez fait {{ count }} clique", 4 | "click_count_other": "Vous avez fait {{ count }} cliques", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur" 6 | } 7 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "csr_counter", 3 | "version": "1.0.0", 4 | "description": "This example showcase how you can use dynamic load with CSR.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "trunk build", 8 | "start": "trunk serve --no-autoreload", 9 | "watch": "trunk serve", 10 | "test": "npx playwright test", 11 | "prestart": "npm run build", 12 | "pretest": "npm run build" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@playwright/test": "^1.45.3", 19 | "@types/node": "^20.14.12" 20 | }, 21 | "imports": { 22 | "#locales/*": "./locales/*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/csr_counter/public/favicon.ico -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | view! { 8 | 9 | 10 | 11 | 12 | } 13 | } 14 | 15 | #[component] 16 | #[allow(non_snake_case)] 17 | pub fn SwitchLang() -> impl IntoView { 18 | let i18n = use_i18n(); 19 | 20 | let on_switch = move |_| { 21 | let new_lang = match i18n.get_locale() { 22 | Locale::en => Locale::fr, 23 | Locale::fr => Locale::en, 24 | }; 25 | i18n.set_locale(new_lang); 26 | }; 27 | 28 | view! { 29 | 30 | } 31 | } 32 | 33 | #[component] 34 | #[allow(non_snake_case)] 35 | fn Counter() -> impl IntoView { 36 | let i18n = use_i18n(); 37 | 38 | let (counter, set_counter) = signal(0); 39 | 40 | let inc = move |_| set_counter.update(|count| *count += 1); 41 | 42 | let count = move || counter.get(); 43 | 44 | view! { 45 |

{t!(i18n, click_count, count = count)}

46 | 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/src/main.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | fn main() { 7 | use app::App; 8 | console_error_panic_hook::set_once(); 9 | leptos::mount::mount_to_body(|| leptos::view! { }) 10 | } 11 | -------------------------------------------------------------------------------- /examples/dynamic_load/csr_counter/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/csr_counter/style/main.scss -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/README.md: -------------------------------------------------------------------------------- 1 | # Hello World Example 2 | 3 | This example showcase how to setup the files to use `leptos_i18n` and easily introduce translations in you application. 4 | 5 | This example use the `actix` backend, but all the code in relation to `leptos_i18n` would be the same using `axum`. 6 | 7 | Check the `axum` Hello World example to compare. 8 | 9 | ## How to run 10 | 11 | Simply use `cargo_leptos` to run it: 12 | 13 | ```sh 14 | cargo leptos watch 15 | ``` 16 | 17 | and to build: 18 | 19 | ```sh 20 | cargo leptos build --release 21 | ``` 22 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello_world_actix", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to implement a basic hello world with Leptos and Actix", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/hello_world_actix/public/favicon.ico -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | } 14 | } 15 | 16 | #[component] 17 | #[allow(non_snake_case)] 18 | pub fn Home() -> impl IntoView { 19 | let i18n = use_i18n(); 20 | 21 | let on_switch = move |_| { 22 | let new_lang = match i18n.get_locale() { 23 | Locale::en => Locale::fr, 24 | Locale::fr => Locale::en, 25 | }; 26 | i18n.set_locale(new_lang); 27 | }; 28 | 29 | view! { 30 |

{t!(i18n, hello_world)}

31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | 5 | leptos_i18n::load_locales!(); 6 | 7 | #[cfg(feature = "hydrate")] 8 | #[wasm_bindgen::prelude::wasm_bindgen] 9 | pub fn hydrate() { 10 | use app::App; 11 | console_error_panic_hook::set_once(); 12 | leptos::mount::hydrate_body(App); 13 | } 14 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_actix/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/hello_world_actix/style/main.scss -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/README.md: -------------------------------------------------------------------------------- 1 | # Hello World Example 2 | 3 | This example showcase how to setup the files to use `leptos_i18n` and easily introduce translations in you application. 4 | 5 | This example use the `axum` backend, but all the code in relation to `leptos_i18n` would be the same using `actix`. 6 | 7 | Check the `actix` Hello World example to compare. 8 | 9 | ## How to run 10 | 11 | Simply use `cargo_leptos` to run it: 12 | 13 | ```sh 14 | cargo leptos watch 15 | ``` 16 | 17 | and to build: 18 | 19 | ```sh 20 | cargo leptos build --release 21 | ``` 22 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language", 4 | "click_count": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter" 6 | } 7 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue", 4 | "click_count": "Vous avez cliqué {{ count }} fois", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur" 6 | } 7 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello_world_axum", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to implement a basic hello world with Leptos and Axum", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/hello_world_axum/public/favicon.ico -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | } 14 | } 15 | 16 | #[component] 17 | #[allow(non_snake_case)] 18 | pub fn Home() -> impl IntoView { 19 | let i18n = use_i18n(); 20 | 21 | let (counter, set_counter) = signal(0); 22 | 23 | let inc = move |_| set_counter.update(|count| *count += 1); 24 | 25 | let on_switch = move |_| { 26 | let new_lang = match i18n.get_locale() { 27 | Locale::en => Locale::fr, 28 | Locale::fr => Locale::en, 29 | }; 30 | i18n.set_locale(new_lang); 31 | }; 32 | 33 | let count = move || counter.get(); 34 | 35 | view! { 36 |

{t!(i18n, hello_world)}

37 | 38 |

39 | {t!{ i18n, 40 | click_count, 41 | count, 42 | = , 43 | }} 44 |

45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/src/fileserv.rs: -------------------------------------------------------------------------------- 1 | use crate::app::App; 2 | use axum::response::Response as AxumResponse; 3 | use axum::{ 4 | body::Body, 5 | extract::State, 6 | http::{Request, Response, StatusCode, Uri}, 7 | response::IntoResponse, 8 | }; 9 | use leptos::prelude::*; 10 | use tower::ServiceExt; 11 | use tower_http::services::{fs::ServeFileSystemResponseBody, ServeDir}; 12 | 13 | pub async fn file_and_error_handler( 14 | uri: Uri, 15 | State(options): State, 16 | req: Request, 17 | ) -> AxumResponse { 18 | let root = options.site_root.clone(); 19 | let res = get_static_file(uri.clone(), &root).await.unwrap(); 20 | 21 | if res.status() == StatusCode::OK { 22 | res.into_response() 23 | } else { 24 | let handler = leptos_axum::render_app_to_stream(App); 25 | handler(req).await.into_response() 26 | } 27 | } 28 | 29 | async fn get_static_file( 30 | uri: Uri, 31 | root: &str, 32 | ) -> Result, (StatusCode, String)> { 33 | let req = Request::builder() 34 | .uri(uri.clone()) 35 | .body(Body::empty()) 36 | .unwrap(); 37 | // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot` 38 | // This path is relative to the cargo root 39 | ServeDir::new(root).oneshot(req).await.map_err(|err| { 40 | ( 41 | StatusCode::INTERNAL_SERVER_ERROR, 42 | format!("Something went wrong: {err}"), 43 | ) 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | #[cfg(feature = "ssr")] 5 | pub mod fileserv; 6 | 7 | leptos_i18n::load_locales!(); 8 | 9 | #[cfg(feature = "hydrate")] 10 | #[wasm_bindgen::prelude::wasm_bindgen] 11 | pub fn hydrate() { 12 | use app::App; 13 | console_error_panic_hook::set_once(); 14 | leptos::mount::hydrate_body(App); 15 | } 16 | -------------------------------------------------------------------------------- /examples/dynamic_load/hello_world_axum/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/hello_world_axum/style/main.scss -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/README.md: -------------------------------------------------------------------------------- 1 | # Hello World Example 2 | 3 | This example showcase how to setup the files to use `leptos_i18n` and easily introduce translations in you application. 4 | 5 | This example use the `axum` backend, but all the code in relation to `leptos_i18n` would be the same using `actix`. 6 | 7 | Check the `actix` Hello World example to compare. 8 | 9 | ## How to run 10 | 11 | Simply use `cargo_leptos` to run it: 12 | 13 | ```sh 14 | cargo leptos watch 15 | ``` 16 | 17 | and to build: 18 | 19 | ```sh 20 | cargo leptos build --release 21 | ``` 22 | -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/locales/en/change_locale.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language" 3 | } -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/locales/en/counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_count": "You clicked {{ count }} times", 3 | "click_to_inc": "Click to increment the counter" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/locales/fr/change_locale.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue" 3 | } -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/locales/fr/counter.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_count": "Vous avez cliqué {{ count }} fois", 3 | "click_to_inc": "Cliquez pour incrémenter le compteur" 4 | } -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello_world_axum", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to implement a basic hello world with Leptos and Axum", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/namespaces/public/favicon.ico -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, counter.click_count, count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/src/fileserv.rs: -------------------------------------------------------------------------------- 1 | use crate::app::App; 2 | use axum::response::Response as AxumResponse; 3 | use axum::{ 4 | body::Body, 5 | extract::State, 6 | http::{Request, Response, StatusCode, Uri}, 7 | response::IntoResponse, 8 | }; 9 | use leptos::prelude::*; 10 | use tower::ServiceExt; 11 | use tower_http::services::{fs::ServeFileSystemResponseBody, ServeDir}; 12 | 13 | pub async fn file_and_error_handler( 14 | uri: Uri, 15 | State(options): State, 16 | req: Request, 17 | ) -> AxumResponse { 18 | let root = options.site_root.clone(); 19 | let res = get_static_file(uri.clone(), &root).await.unwrap(); 20 | 21 | if res.status() == StatusCode::OK { 22 | res.into_response() 23 | } else { 24 | let handler = leptos_axum::render_app_to_stream(App); 25 | handler(req).await.into_response() 26 | } 27 | } 28 | 29 | async fn get_static_file( 30 | uri: Uri, 31 | root: &str, 32 | ) -> Result, (StatusCode, String)> { 33 | let req = Request::builder() 34 | .uri(uri.clone()) 35 | .body(Body::empty()) 36 | .unwrap(); 37 | // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot` 38 | // This path is relative to the cargo root 39 | ServeDir::new(root).oneshot(req).await.map_err(|err| { 40 | ( 41 | StatusCode::INTERNAL_SERVER_ERROR, 42 | format!("Something went wrong: {err}"), 43 | ) 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | #[cfg(feature = "ssr")] 5 | pub mod fileserv; 6 | 7 | leptos_i18n::load_locales!(); 8 | 9 | #[cfg(feature = "hydrate")] 10 | #[wasm_bindgen::prelude::wasm_bindgen] 11 | pub fn hydrate() { 12 | use app::App; 13 | console_error_panic_hook::set_once(); 14 | leptos::mount::hydrate_body(App); 15 | } 16 | -------------------------------------------------------------------------------- /examples/dynamic_load/namespaces/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/dynamic_load/namespaces/style/main.scss -------------------------------------------------------------------------------- /examples/ssr/axum_island/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/ssr/axum_island/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/ssr/axum_island/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/ssr/axum_island/README.md: -------------------------------------------------------------------------------- 1 | # Hello World Example 2 | 3 | This example showcase how to use `leptos_i18n` with experimental `island` feature from Leptos. 4 | 5 | ## How to run 6 | 7 | Simply use `cargo_leptos` to run it: 8 | 9 | ```sh 10 | cargo leptos watch 11 | ``` 12 | 13 | and to build: 14 | 15 | ```sh 16 | cargo leptos build --release 17 | ``` 18 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language", 4 | "click_count": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter" 6 | } 7 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue", 4 | "click_count": "Vous avez cliqué {{ count }} fois", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur" 6 | } 7 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "axum_island", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to use `leptos_i18n` with experimental `island` feature from Leptos.", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/axum_island/public/favicon.ico -------------------------------------------------------------------------------- /examples/ssr/axum_island/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | view! { 8 | 9 |

10 | {ti!(HelloWorld, hello_world)} 11 |

12 | 13 | 14 |
15 | } 16 | } 17 | 18 | #[island] 19 | #[allow(non_snake_case)] 20 | fn Counter() -> impl IntoView { 21 | let i18n = use_i18n(); 22 | 23 | let (counter, set_counter) = signal(0); 24 | 25 | let inc = move |_| set_counter.update(|count| *count += 1); 26 | 27 | let count = move || counter.get(); 28 | 29 | view! { 30 |

31 | {t!{ 32 | i18n, 33 | click_count, 34 | count, 35 | = , 36 | }} 37 |

38 | 39 | } 40 | } 41 | 42 | #[island] 43 | #[allow(non_snake_case)] 44 | fn ChangeLang() -> impl IntoView { 45 | let i18n = use_i18n(); 46 | 47 | let on_switch = move |_| { 48 | let new_lang = match i18n.get_locale() { 49 | Locale::en => Locale::fr, 50 | Locale::fr => Locale::en, 51 | }; 52 | i18n.set_locale(new_lang); 53 | }; 54 | 55 | view! { 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | 5 | leptos_i18n::load_locales!(); 6 | 7 | #[cfg(feature = "hydrate")] 8 | #[wasm_bindgen::prelude::wasm_bindgen] 9 | pub fn hydrate() { 10 | console_error_panic_hook::set_once(); 11 | leptos::mount::hydrate_islands(); 12 | } 13 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/src/main.rs: -------------------------------------------------------------------------------- 1 | use axum::Router; 2 | use axum_island::app::App; 3 | use leptos::prelude::*; 4 | use leptos_axum::{generate_route_list, LeptosRoutes}; 5 | 6 | #[tokio::main] 7 | async fn main() { 8 | // Setting this to None means we'll be using cargo-leptos and its env vars 9 | let conf = get_configuration(None).unwrap(); 10 | let leptos_options = conf.leptos_options; 11 | let addr = leptos_options.site_addr; 12 | let routes = generate_route_list(App); 13 | 14 | // build our application with a route 15 | let app = Router::new() 16 | .leptos_routes(&leptos_options, routes, { 17 | let leptos_options = leptos_options.clone(); 18 | move || shell(leptos_options.clone()) 19 | }) 20 | .fallback(leptos_axum::file_and_error_handler(shell)) 21 | .with_state(leptos_options); 22 | 23 | // run our app with hyper 24 | // `axum::Server` is a re-export of `hyper::Server` 25 | let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); 26 | println!("listening on http://{}", &addr); 27 | axum::serve(listener, app.into_make_service()) 28 | .await 29 | .unwrap(); 30 | } 31 | 32 | pub fn shell(options: LeptosOptions) -> impl IntoView { 33 | view! { 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /examples/ssr/axum_island/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/axum_island/style/main.scss -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/README.md: -------------------------------------------------------------------------------- 1 | # Hello World Example 2 | 3 | This example showcase how to setup the files to use `leptos_i18n` and easily introduce translations in you application. 4 | 5 | This example use the `actix` backend, but all the code in relation to `leptos_i18n` would be the same using `axum`. 6 | 7 | Check the `axum` Hello World example to compare. 8 | 9 | ## How to run 10 | 11 | Simply use `cargo_leptos` to run it: 12 | 13 | ```sh 14 | cargo leptos watch 15 | ``` 16 | 17 | and to build: 18 | 19 | ```sh 20 | cargo leptos build --release 21 | ``` 22 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language" 4 | } -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue" 4 | } -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello_world_actix", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to implement a basic hello world with Leptos and Actix", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/hello_world_actix/public/favicon.ico -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | } 14 | } 15 | 16 | #[component] 17 | #[allow(non_snake_case)] 18 | pub fn Home() -> impl IntoView { 19 | let i18n = use_i18n(); 20 | 21 | let on_switch = move |_| { 22 | let new_lang = match i18n.get_locale() { 23 | Locale::en => Locale::fr, 24 | Locale::fr => Locale::en, 25 | }; 26 | i18n.set_locale(new_lang); 27 | }; 28 | 29 | view! { 30 |

{t!(i18n, hello_world)}

31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | 5 | leptos_i18n::load_locales!(); 6 | 7 | #[cfg(feature = "hydrate")] 8 | #[wasm_bindgen::prelude::wasm_bindgen] 9 | pub fn hydrate() { 10 | use app::App; 11 | console_error_panic_hook::set_once(); 12 | leptos::mount::hydrate_body(App); 13 | } 14 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_actix/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/hello_world_actix/style/main.scss -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/README.md: -------------------------------------------------------------------------------- 1 | # Hello World Example 2 | 3 | This example showcase how to setup the files to use `leptos_i18n` and easily introduce translations in you application. 4 | 5 | This example use the `axum` backend, but all the code in relation to `leptos_i18n` would be the same using `actix`. 6 | 7 | Check the `actix` Hello World example to compare. 8 | 9 | ## How to run 10 | 11 | Simply use `cargo_leptos` to run it: 12 | 13 | ```sh 14 | cargo leptos watch 15 | ``` 16 | 17 | and to build: 18 | 19 | ```sh 20 | cargo leptos build --release 21 | ``` 22 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language", 4 | "click_count": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter" 6 | } 7 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue", 4 | "click_count": "Vous avez cliqué {{ count }} fois", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur" 6 | } 7 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hello_world_axum", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to implement a basic hello world with Leptos and Axum", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/hello_world_axum/public/favicon.ico -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | } 14 | } 15 | 16 | #[component] 17 | #[allow(non_snake_case)] 18 | pub fn Home() -> impl IntoView { 19 | let i18n = use_i18n(); 20 | 21 | let (counter, set_counter) = signal(0); 22 | 23 | let inc = move |_| set_counter.update(|count| *count += 1); 24 | 25 | let on_switch = move |_| { 26 | let new_lang = match i18n.get_locale() { 27 | Locale::en => Locale::fr, 28 | Locale::fr => Locale::en, 29 | }; 30 | i18n.set_locale(new_lang); 31 | }; 32 | 33 | let count = move || counter.get(); 34 | 35 | view! { 36 |

{t!(i18n, hello_world)}

37 | 38 |

39 | {t!{ i18n, 40 | click_count, 41 | count, 42 | = , 43 | }} 44 |

45 | 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/src/fileserv.rs: -------------------------------------------------------------------------------- 1 | use crate::app::App; 2 | use axum::response::Response as AxumResponse; 3 | use axum::{ 4 | body::Body, 5 | extract::State, 6 | http::{Request, Response, StatusCode, Uri}, 7 | response::IntoResponse, 8 | }; 9 | use leptos::prelude::*; 10 | use tower::ServiceExt; 11 | use tower_http::services::{fs::ServeFileSystemResponseBody, ServeDir}; 12 | 13 | pub async fn file_and_error_handler( 14 | uri: Uri, 15 | State(options): State, 16 | req: Request, 17 | ) -> AxumResponse { 18 | let root = options.site_root.clone(); 19 | let res = get_static_file(uri.clone(), &root).await.unwrap(); 20 | 21 | if res.status() == StatusCode::OK { 22 | res.into_response() 23 | } else { 24 | let handler = leptos_axum::render_app_to_stream(App); 25 | handler(req).await.into_response() 26 | } 27 | } 28 | 29 | async fn get_static_file( 30 | uri: Uri, 31 | root: &str, 32 | ) -> Result, (StatusCode, String)> { 33 | let req = Request::builder() 34 | .uri(uri.clone()) 35 | .body(Body::empty()) 36 | .unwrap(); 37 | // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot` 38 | // This path is relative to the cargo root 39 | ServeDir::new(root).oneshot(req).await.map_err(|err| { 40 | ( 41 | StatusCode::INTERNAL_SERVER_ERROR, 42 | format!("Something went wrong: {err}"), 43 | ) 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | #[cfg(feature = "ssr")] 5 | pub mod fileserv; 6 | 7 | leptos_i18n::load_locales!(); 8 | 9 | #[cfg(feature = "hydrate")] 10 | #[wasm_bindgen::prelude::wasm_bindgen] 11 | pub fn hydrate() { 12 | use app::App; 13 | console_error_panic_hook::set_once(); 14 | leptos::mount::hydrate_body(App); 15 | } 16 | -------------------------------------------------------------------------------- /examples/ssr/hello_world_axum/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/hello_world_axum/style/main.scss -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/README.md: -------------------------------------------------------------------------------- 1 | # Routing SSR 2 | 3 | This example showcase how to setup the router using `leptos_i18n` in a SSR project. 4 | 5 | ## How to run 6 | 7 | Simply use `cargo_leptos` to run it: 8 | 9 | ```sh 10 | cargo leptos watch 11 | ``` 12 | 13 | and to build: 14 | 15 | ```sh 16 | cargo leptos build --release 17 | ``` 18 | -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Hello World!", 3 | "click_to_change_lang": "Click to change language", 4 | "click_count": "You clicked {{ count }} times", 5 | "click_to_inc": "Click to increment the counter", 6 | "go_home": "Homepage", 7 | "go_counter": "Counter" 8 | } 9 | -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "hello_world": "Bonjour le monde!", 3 | "click_to_change_lang": "Cliquez pour changez de langue", 4 | "click_count": "Vous avez cliqué {{ count }} fois", 5 | "click_to_inc": "Cliquez pour incrémenter le compteur", 6 | "go_home": "Accueil", 7 | "go_counter": "Compteur" 8 | } 9 | -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "routing_ssr", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to use routing with SSR", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/routing_ssr/public/favicon.ico -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/src/fileserv.rs: -------------------------------------------------------------------------------- 1 | use crate::app::App; 2 | use axum::response::Response as AxumResponse; 3 | use axum::{ 4 | body::Body, 5 | extract::State, 6 | http::{Request, Response, StatusCode, Uri}, 7 | response::IntoResponse, 8 | }; 9 | use leptos::prelude::*; 10 | use tower::ServiceExt; 11 | use tower_http::services::{fs::ServeFileSystemResponseBody, ServeDir}; 12 | 13 | pub async fn file_and_error_handler( 14 | uri: Uri, 15 | State(options): State, 16 | req: Request, 17 | ) -> AxumResponse { 18 | let root = options.site_root.clone(); 19 | let res = get_static_file(uri.clone(), &root).await.unwrap(); 20 | 21 | if res.status() == StatusCode::OK { 22 | res.into_response() 23 | } else { 24 | let handler = leptos_axum::render_app_to_stream(App); 25 | handler(req).await.into_response() 26 | } 27 | } 28 | 29 | async fn get_static_file( 30 | uri: Uri, 31 | root: &str, 32 | ) -> Result, (StatusCode, String)> { 33 | let req = Request::builder() 34 | .uri(uri.clone()) 35 | .body(Body::empty()) 36 | .unwrap(); 37 | // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot` 38 | // This path is relative to the cargo root 39 | ServeDir::new(root).oneshot(req).await.map_err(|err| { 40 | ( 41 | StatusCode::INTERNAL_SERVER_ERROR, 42 | format!("Something went wrong: {err}"), 43 | ) 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/src/lib.rs: -------------------------------------------------------------------------------- 1 | // #![deny(warnings)] 2 | 3 | pub mod app; 4 | #[cfg(feature = "ssr")] 5 | pub mod fileserv; 6 | leptos_i18n::load_locales!(); 7 | 8 | #[cfg(feature = "hydrate")] 9 | #[wasm_bindgen::prelude::wasm_bindgen] 10 | pub fn hydrate() { 11 | use app::App; 12 | console_error_panic_hook::set_once(); 13 | leptos::mount::hydrate_body(|| leptos::view! { }); 14 | } 15 | -------------------------------------------------------------------------------- /examples/ssr/routing_ssr/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/routing_ssr/style/main.scss -------------------------------------------------------------------------------- /examples/ssr/workspace/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode 4 | 5 | node_modules/ 6 | /test-results/ 7 | /playwright-report/ 8 | /blob-report/ 9 | /playwright/.cache/ -------------------------------------------------------------------------------- /examples/ssr/workspace/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /examples/ssr/workspace/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /examples/ssr/workspace/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "counter/locales" 4 | } -------------------------------------------------------------------------------- /examples/ssr/workspace/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["client", "server"] 4 | 5 | [workspace.dependencies] 6 | leptos_i18n = { path = "../../../leptos_i18n" } 7 | 8 | [[workspace.metadata.leptos]] 9 | name = "counter" 10 | bin-package = "server" 11 | 12 | lib-package = "client" 13 | lib-features = ["hydrate"] 14 | 15 | reload-port = 3001 16 | 17 | # [Optional] Command to use when running end2end tests. It will run in the end2end dir. 18 | end2end-cmd = "npx playwright test" 19 | end2end-dir = "e2e" 20 | 21 | # watch changes on the locales folder 22 | watch-additional-files = ["client/locales"] 23 | -------------------------------------------------------------------------------- /examples/ssr/workspace/README.md: -------------------------------------------------------------------------------- 1 | # Counter Example 2 | 3 | This example showcase one way to setup the library in a workspace environment. 4 | 5 | ## How to run 6 | 7 | Simply use `cargo_leptos` to run it: 8 | 9 | ```sh 10 | cargo leptos watch 11 | ``` 12 | 13 | and to build: 14 | 15 | ```sh 16 | cargo leptos build --release 17 | ``` 18 | -------------------------------------------------------------------------------- /examples/ssr/workspace/client/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target -------------------------------------------------------------------------------- /examples/ssr/workspace/client/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "client" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib", "rlib"] 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | actix-web = { version = "4.4", optional = true, features = ["macros"] } 13 | leptos = { version = "0.7.0" } 14 | leptos_meta = { version = "0.7.0" } 15 | leptos_actix = { version = "0.7.0", optional = true } 16 | leptos_i18n = { workspace = true, features = ["track_locale_files"] } 17 | serde = { version = "1", features = ["derive"] } 18 | console_error_panic_hook = { version = "0.1", optional = true } 19 | wasm-bindgen = "0.2" 20 | 21 | [features] 22 | default = ["hydrate", "ssr"] 23 | hydrate = [ 24 | "dep:console_error_panic_hook", 25 | "leptos/hydrate", 26 | "leptos_i18n/hydrate", 27 | ] 28 | ssr = [ 29 | "dep:actix-web", 30 | "dep:leptos_actix", 31 | "leptos/ssr", 32 | "leptos_meta/ssr", 33 | "leptos_i18n/actix", 34 | ] 35 | 36 | [package.metadata.leptos-i18n] 37 | default = "en" 38 | locales = ["en", "fr"] 39 | -------------------------------------------------------------------------------- /examples/ssr/workspace/client/locales/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "click_count": "You clicked {{ count }} times", 4 | "click_to_inc": "Click to increment the counter" 5 | } -------------------------------------------------------------------------------- /examples/ssr/workspace/client/locales/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "click_count": "Vous avez cliqué {{ count }} fois", 4 | "click_to_inc": "Cliquez pour incrémenter le compteur" 5 | } -------------------------------------------------------------------------------- /examples/ssr/workspace/client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/workspace/client/public/favicon.ico -------------------------------------------------------------------------------- /examples/ssr/workspace/client/src/app.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use leptos::prelude::*; 3 | 4 | #[component] 5 | #[allow(non_snake_case)] 6 | pub fn App() -> impl IntoView { 7 | leptos_meta::provide_meta_context(); 8 | 9 | view! { 10 | 11 | 12 | 13 | 14 | } 15 | } 16 | 17 | #[component] 18 | #[allow(non_snake_case)] 19 | pub fn SwitchLang() -> impl IntoView { 20 | let i18n = use_i18n(); 21 | 22 | let on_switch = move |_| { 23 | let new_lang = match i18n.get_locale() { 24 | Locale::en => Locale::fr, 25 | Locale::fr => Locale::en, 26 | }; 27 | i18n.set_locale(new_lang); 28 | }; 29 | 30 | view! { 31 | 32 | } 33 | } 34 | 35 | #[component] 36 | #[allow(non_snake_case)] 37 | fn Counter() -> impl IntoView { 38 | let i18n = use_i18n(); 39 | 40 | let (counter, set_counter) = signal(0); 41 | 42 | let inc = move |_| set_counter.update(|count| *count += 1); 43 | 44 | let count = move || counter.get(); 45 | 46 | view! { 47 |

{t!(i18n, click_count, count)}

48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /examples/ssr/workspace/client/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | pub mod app; 4 | leptos_i18n::load_locales!(); 5 | 6 | #[cfg(feature = "hydrate")] 7 | #[wasm_bindgen::prelude::wasm_bindgen] 8 | pub fn hydrate() { 9 | use app::App; 10 | console_error_panic_hook::set_once(); 11 | leptos::mount::hydrate_body(App); 12 | } 13 | -------------------------------------------------------------------------------- /examples/ssr/workspace/client/style/main.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Baptistemontan/leptos_i18n/d82366f1ca4a8ae91f3ba107047768b01622625f/examples/ssr/workspace/client/style/main.scss -------------------------------------------------------------------------------- /examples/ssr/workspace/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "worspace", 3 | "version": "1.0.0", 4 | "description": "This example showcase how to setup leptos_i18n in a worspace environment", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "cargo leptos build", 8 | "start": "cargo leptos serve", 9 | "test": "npx playwright test", 10 | "prestart": "npm run build", 11 | "pretest": "npm run build" 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "devDependencies": { 17 | "@playwright/test": "^1.45.3", 18 | "@types/node": "^20.14.12" 19 | }, 20 | "imports": { 21 | "#locales/*": "./client/locales/*" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /examples/ssr/workspace/server/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target -------------------------------------------------------------------------------- /examples/ssr/workspace/server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "server" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | actix-files = "0.6" 10 | actix-web = { version = "4.4", features = ["macros"] } 11 | leptos = { version = "0.7.0", features = ["ssr"] } 12 | leptos_meta = { version = "0.7.0", features = ["ssr"] } 13 | leptos_actix = { version = "0.7.0" } 14 | serde = { version = "1", features = ["derive"] } 15 | client = { path = "../client", default-features = false, features = ["ssr"] } 16 | -------------------------------------------------------------------------------- /examples/utils/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | dist/ -------------------------------------------------------------------------------- /examples/utils/README.md: -------------------------------------------------------------------------------- 1 | # e2e utils package 2 | 3 | This package is utils for developping the e2e tests of the examples 4 | -------------------------------------------------------------------------------- /examples/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "utils", 3 | "version": "1.0.0", 4 | "description": "This package is utils for developping the e2e tests of the examples", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "postinstall": "npm run build", 9 | "build": "npx tsc" 10 | }, 11 | "author": "", 12 | "license": "ISC", 13 | "devDependencies": { 14 | "@playwright/test": "^1.45.3", 15 | "@types/node": "^20.14.12", 16 | "typescript": "^5.5.4" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /examples/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es2019", 5 | "declaration": true, 6 | "outDir": "./dist" 7 | }, 8 | "include": [ 9 | "src/**/*" 10 | ] 11 | } -------------------------------------------------------------------------------- /leptos_i18n/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /leptos_i18n/src/macro_helpers/interpol_args.rs: -------------------------------------------------------------------------------- 1 | use leptos::IntoView; 2 | 3 | /// Marker trait for a type that can be used as an interpolation variable. 4 | pub trait InterpolateVar: IntoView + Clone + 'static + Send + Sync {} 5 | 6 | impl InterpolateVar for T {} 7 | 8 | /// Marker trait for a type that can be used as an interpolation component. 9 | pub trait InterpolateComp: 10 | Fn(leptos::children::ChildrenFn) -> O + Clone + 'static + Send + Sync 11 | { 12 | } 13 | 14 | impl< 15 | O: IntoView + 'static, 16 | T: Fn(leptos::children::ChildrenFn) -> O + Clone + 'static + Send + Sync, 17 | > InterpolateComp for T 18 | { 19 | } 20 | 21 | /// Marker trait for a type that can be used to produce a count for a range key. 22 | pub trait InterpolateRangeCount: Fn() -> T + Clone + 'static + Send + Sync {} 23 | 24 | impl T + Clone + 'static + Send + Sync> InterpolateRangeCount for F {} 25 | 26 | /// Marker trait for a type that can produce a `icu::plurals::PluralOperands` 27 | #[cfg(feature = "plurals")] 28 | pub trait InterpolatePluralCount: Fn() -> Self::Count + Clone + 'static + Send + Sync { 29 | /// The returned value that can be turned into a `icu::plurals::PluralOperands` 30 | type Count: Into; 31 | } 32 | 33 | #[cfg(feature = "plurals")] 34 | impl, F: Fn() -> T + Clone + 'static + Send + Sync> 35 | InterpolatePluralCount for F 36 | { 37 | type Count = T; 38 | } 39 | -------------------------------------------------------------------------------- /leptos_i18n/src/macro_helpers/scope.rs: -------------------------------------------------------------------------------- 1 | use crate::{scopes::ScopedLocale, ConstScope, I18nContext, Locale, Scope}; 2 | 3 | #[doc(hidden)] 4 | pub const fn scope_ctx_util, NS: Scope>( 5 | ctx: I18nContext, 6 | map_fn: fn(OS) -> NS, 7 | ) -> I18nContext { 8 | let old_scope = ConstScope::::new(); 9 | let new_scope = old_scope.map(map_fn); 10 | ctx.scope(new_scope) 11 | } 12 | 13 | #[doc(hidden)] 14 | pub fn scope_locale_util, NS: Scope>( 15 | locale: L, 16 | map_fn: fn(>::Keys) -> NS, 17 | ) -> ScopedLocale { 18 | let _ = map_fn; 19 | ScopedLocale::new(locale.to_base_locale()) 20 | } 21 | -------------------------------------------------------------------------------- /leptos_i18n_build/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /leptos_i18n_build/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leptos_i18n_build" 3 | version = { workspace = true } 4 | edition = "2021" 5 | authors = ["Baptiste de Montangon"] 6 | license = "MIT" 7 | repository = "https://github.com/Baptistemontan/leptos_i18n" 8 | description = "build.rs utilities for the leptos_i18n crate" 9 | readme = "../README.md" 10 | 11 | [dependencies] 12 | leptos_i18n_parser = { workspace = true } 13 | icu_datagen = { workspace = true, features = ["experimental_components"] } 14 | icu_provider = { workspace = true } 15 | icu_locid = { workspace = true } 16 | 17 | [features] 18 | default = ["json_files"] 19 | json_files = ["leptos_i18n_parser/json_files"] 20 | yaml_files = ["leptos_i18n_parser/yaml_files"] 21 | json5_files = ["leptos_i18n_parser/json5_files"] 22 | -------------------------------------------------------------------------------- /leptos_i18n_macro/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /leptos_i18n_macro/src/load_locales/locale.rs: -------------------------------------------------------------------------------- 1 | use quote::{quote, ToTokens}; 2 | 3 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 4 | pub enum LiteralType { 5 | String, 6 | Bool, 7 | Signed, 8 | Unsigned, 9 | Float, 10 | } 11 | 12 | impl From for LiteralType { 13 | fn from(value: leptos_i18n_parser::parse_locales::locale::LiteralType) -> Self { 14 | match value { 15 | leptos_i18n_parser::parse_locales::locale::LiteralType::String => Self::String, 16 | leptos_i18n_parser::parse_locales::locale::LiteralType::Bool => Self::Bool, 17 | leptos_i18n_parser::parse_locales::locale::LiteralType::Signed => Self::Signed, 18 | leptos_i18n_parser::parse_locales::locale::LiteralType::Unsigned => Self::Unsigned, 19 | leptos_i18n_parser::parse_locales::locale::LiteralType::Float => Self::Float, 20 | } 21 | } 22 | } 23 | 24 | impl ToTokens for LiteralType { 25 | fn to_token_stream(&self) -> proc_macro2::TokenStream { 26 | match self { 27 | LiteralType::String => quote!(&'static str), 28 | LiteralType::Bool => quote!(bool), 29 | LiteralType::Signed => quote!(i64), 30 | LiteralType::Unsigned => quote!(u64), 31 | LiteralType::Float => quote!(f64), 32 | } 33 | } 34 | 35 | fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { 36 | tokens.extend(self.to_token_stream()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /leptos_i18n_macro/src/load_locales/tracking.rs: -------------------------------------------------------------------------------- 1 | pub fn generate_file_tracking(tracked_files: Option>) -> proc_macro2::TokenStream { 2 | if cfg!(all( 3 | not(feature = "track_locale_files"), 4 | not(feature = "nightly") 5 | )) { 6 | return proc_macro2::TokenStream::new(); 7 | } 8 | 9 | let Some(paths) = tracked_files else { 10 | return proc_macro2::TokenStream::new(); 11 | }; 12 | 13 | if cfg!(all( 14 | feature = "track_locale_files", 15 | not(feature = "nightly") 16 | )) { 17 | quote::quote!(#(const _: &[u8] = include_bytes!(#paths);)*) 18 | } else { 19 | #[cfg(feature = "nightly")] 20 | for path in paths { 21 | proc_macro::tracked_path::path(path); 22 | } 23 | 24 | proc_macro2::TokenStream::new() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /leptos_i18n_macro/src/load_locales/warning.rs: -------------------------------------------------------------------------------- 1 | use leptos_i18n_parser::parse_locales::warning::{Warning, Warnings}; 2 | use proc_macro2::TokenStream; 3 | use quote::{format_ident, quote}; 4 | 5 | fn warning_fn((index, warning): (usize, &Warning)) -> TokenStream { 6 | let msg = warning.to_string(); 7 | let fn_name = format_ident!("w{}", index); 8 | quote! { 9 | #[deprecated(note = #msg)] 10 | fn #fn_name() { 11 | unimplemented!() 12 | } 13 | } 14 | } 15 | 16 | fn emit_warning(warning: &Warning) { 17 | let _ = warning; 18 | #[cfg(feature = "nightly")] 19 | { 20 | use proc_macro::Diagnostic; 21 | 22 | Diagnostic::new(proc_macro::Level::Warning, warning.to_string()).emit(); 23 | } 24 | } 25 | 26 | fn generate_warnings_inner(warnings: &[Warning]) -> TokenStream { 27 | let warning_fns = warnings.iter().enumerate().map(warning_fn); 28 | 29 | let fn_calls = (0..warnings.len()).map(|i| { 30 | let fn_name = format_ident!("w{}", i); 31 | quote!(#fn_name();) 32 | }); 33 | 34 | quote! { 35 | #[allow(unused)] 36 | fn warnings() { 37 | #( 38 | #warning_fns 39 | )* 40 | 41 | #( 42 | #fn_calls 43 | )* 44 | } 45 | } 46 | } 47 | 48 | pub fn generate_warnings(warnings: Warnings) -> Option { 49 | let ws = warnings.into_inner(); 50 | 51 | if cfg!(not(feature = "nightly")) { 52 | if ws.is_empty() { 53 | None 54 | } else { 55 | Some(generate_warnings_inner(&ws)) 56 | } 57 | } else { 58 | for warning in &ws { 59 | emit_warning(warning) 60 | } 61 | None 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /leptos_i18n_macro/src/t_macro/parsed_input.rs: -------------------------------------------------------------------------------- 1 | use syn::{token::Comma, Expr}; 2 | 3 | use crate::utils::Keys; 4 | 5 | use super::interpolate::InterpolatedValue; 6 | 7 | pub struct ParsedInput { 8 | pub context: Expr, 9 | pub keys: Keys, 10 | pub interpolations: Option>, 11 | } 12 | 13 | impl syn::parse::Parse for ParsedInput { 14 | fn parse(input: syn::parse::ParseStream) -> syn::Result { 15 | let context = input.parse()?; 16 | input.parse::()?; 17 | let keys = input.parse()?; 18 | let comma = input.parse::(); 19 | let interpolations = match comma { 20 | Ok(_) => { 21 | let interpolations = input 22 | .parse_terminated(InterpolatedValue::parse, Comma)? 23 | .into_iter() 24 | .collect(); 25 | Some(interpolations) 26 | } 27 | Err(_) if input.is_empty() => None, 28 | Err(err) => return Err(err), 29 | }; 30 | Ok(ParsedInput { 31 | context, 32 | keys, 33 | interpolations, 34 | }) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /leptos_i18n_macro/src/utils/scoped.rs: -------------------------------------------------------------------------------- 1 | use proc_macro2::TokenStream; 2 | use quote::quote; 3 | use syn::parse_macro_input; 4 | 5 | use super::Keys; 6 | 7 | struct ScopeParsedInput { 8 | pub context: syn::Expr, 9 | pub keys: Keys, 10 | } 11 | 12 | impl syn::parse::Parse for ScopeParsedInput { 13 | fn parse(input: syn::parse::ParseStream) -> syn::Result { 14 | let context = input.parse()?; 15 | input.parse::()?; 16 | let keys = input.parse()?; 17 | Ok(ScopeParsedInput { context, keys }) 18 | } 19 | } 20 | 21 | pub fn scope_i18n(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { 22 | let input = parse_macro_input!(tokens as ScopeParsedInput); 23 | scope_i18n_inner(input).into() 24 | } 25 | 26 | fn scope_i18n_inner(input: ScopeParsedInput) -> TokenStream { 27 | let ScopeParsedInput { context, keys } = input; 28 | quote! {{ 29 | leptos_i18n::__private::scope_ctx_util(#context, |_k| _k.#keys()) 30 | }} 31 | } 32 | 33 | pub fn use_i18n_scoped(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { 34 | let input = parse_macro_input!(tokens as Keys); 35 | use_i18n_scoped_inner(input).into() 36 | } 37 | 38 | fn use_i18n_scoped_inner(keys: Keys) -> TokenStream { 39 | quote! {{ 40 | leptos_i18n::__private::scope_ctx_util(use_i18n(), |_k| _k.#keys()) 41 | }} 42 | } 43 | 44 | pub fn scope_locale(tokens: proc_macro::TokenStream) -> proc_macro::TokenStream { 45 | let input = parse_macro_input!(tokens as ScopeParsedInput); 46 | scope_locale_inner(input).into() 47 | } 48 | 49 | fn scope_locale_inner(input: ScopeParsedInput) -> TokenStream { 50 | let ScopeParsedInput { 51 | context: locale, 52 | keys, 53 | } = input; 54 | quote! {{ leptos_i18n::__private::scope_locale_util(#locale, |_k| _k.#keys()) }} 55 | } 56 | -------------------------------------------------------------------------------- /leptos_i18n_parser/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /leptos_i18n_parser/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leptos_i18n_parser" 3 | version = { workspace = true } 4 | edition = "2021" 5 | authors = ["Baptiste de Montangon"] 6 | license = "MIT" 7 | repository = "https://github.com/Baptistemontan/leptos_i18n" 8 | description = "parser for the leptos_i18n crate" 9 | readme = "../README.md" 10 | 11 | [dependencies] 12 | icu_locid = { workspace = true } 13 | icu_plurals = { workspace = true, features = ["compiled_data"] } 14 | serde = { version = "1", features = ["rc"] } 15 | serde_json = { version = "1" } 16 | serde_yaml = { version = "0.9" } 17 | toml = "0.8" 18 | fixed_decimal = { workspace = true, features = ["ryu"] } 19 | json5 = { version = "0.4" } 20 | quote = { version = "1", optional = true } 21 | syn = { version = "2.0", optional = true } 22 | proc-macro2 = { version = "1", optional = true } 23 | tinystr = { workspace = true } 24 | 25 | [features] 26 | default = ["json_files"] 27 | quote = ["dep:quote", "dep:syn", "dep:proc-macro2"] 28 | json_files = [] 29 | yaml_files = [] 30 | json5_files = [] 31 | plurals = [] 32 | format_datetime = [] 33 | format_list = [] 34 | format_nums = [] 35 | format_currency = ["format_nums"] 36 | suppress_key_warnings = [] 37 | -------------------------------------------------------------------------------- /leptos_i18n_parser/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![forbid(unsafe_code)] 2 | #![deny(warnings)] 3 | 4 | pub mod parse_locales; 5 | pub mod utils; 6 | -------------------------------------------------------------------------------- /leptos_i18n_parser/src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod formatter; 2 | pub mod key; 3 | 4 | use std::fmt::Debug; 5 | 6 | pub use key::{Key, KeyPath}; 7 | 8 | /// We should avoid to panic as much as possible, and return the Error enum instead, 9 | /// but there is cases where unwrap *should* be good, like when accessing a value in a Map where the keys are already known 10 | /// This trait serves as a easy unwrap where the code position can be given. 11 | pub trait UnwrapAt { 12 | type Value; 13 | 14 | fn unwrap_at(self, location: &str) -> Self::Value; 15 | } 16 | 17 | impl UnwrapAt for Option { 18 | type Value = T; 19 | 20 | #[track_caller] 21 | fn unwrap_at(self, location: &str) -> Self::Value { 22 | let msg = format!("Unexpected None value at {}. If you got this error please open an issue on the leptos_i18n github repo.", location); 23 | self.expect(&msg) 24 | } 25 | } 26 | 27 | impl UnwrapAt for Result { 28 | type Value = T; 29 | 30 | #[track_caller] 31 | fn unwrap_at(self, location: &str) -> Self::Value { 32 | let msg = format!("Unexpected Err value at {}. If you got this error please open an issue on the leptos_i18n github repo.", location); 33 | self.expect(&msg) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /leptos_i18n_router/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /Cargo.lock 3 | -------------------------------------------------------------------------------- /leptos_i18n_router/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "leptos_i18n_router" 3 | version = { workspace = true } 4 | edition = "2021" 5 | authors = ["Baptiste de Montangon"] 6 | license = "MIT" 7 | repository = "https://github.com/Baptistemontan/leptos_i18n" 8 | description = "Translations integration helper for the Leptos web framework" 9 | readme = "../README.md" 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | 13 | [dependencies] 14 | leptos_i18n = { workspace = true } 15 | leptos = { workspace = true } 16 | leptos_router = { workspace = true } 17 | 18 | [features] 19 | ssr = ["leptos/ssr", "leptos_router/ssr", "leptos_i18n/ssr"] 20 | 21 | 22 | [package.metadata.cargo-all-features] 23 | denylist = [] 24 | skip_feature_sets = [] 25 | always_include_features = [] 26 | -------------------------------------------------------------------------------- /leptos_i18n_router/src/components.rs: -------------------------------------------------------------------------------- 1 | use std::marker::PhantomData; 2 | 3 | use leptos::component; 4 | use leptos_i18n::Locale; 5 | use leptos_router::{components::RouteChildren, ChooseView, MatchNestedRoutes, SsrMode}; 6 | 7 | #[component(transparent)] 8 | pub fn I18nRoute( 9 | /// The base path of this application. 10 | /// If you setup your i18n route such that the path is `/foo/:locale/bar`, 11 | /// the expected base path is `"foo"`, `"/foo"`, `"foo/"` or `"/foo/"`. 12 | /// Defaults to `"/"`. 13 | #[prop(default = "/")] 14 | base_path: &'static str, 15 | /// The view that should be shown when this route is matched. This can be any function 16 | /// that returns a type that implements [`IntoView`] (like `|| view! {

"Show this"

})` 17 | /// or `|| view! { ` } or even, for a component with no props, `MyComponent`). 18 | /// If you use nested routes you can just set it to `view=Outlet` 19 | view: View, 20 | /// The mode that this route prefers during server-side rendering. Defaults to out-of-order streaming 21 | #[prop(optional)] 22 | ssr: SsrMode, 23 | /// `children` may be empty or include nested routes. 24 | children: RouteChildren, 25 | #[prop(optional)] _marker: PhantomData, 26 | ) -> impl MatchNestedRoutes + 'static + Send + Sync + Clone 27 | where 28 | View: ChooseView + 'static + Send + Sync, 29 | Chil: MatchNestedRoutes + 'static + Send + Sync + Clone, 30 | L: Locale, 31 | { 32 | crate::routing::i18n_routing::(base_path, children, ssr, view) 33 | } 34 | -------------------------------------------------------------------------------- /leptos_i18n_router/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(missing_docs)] 2 | #![forbid(unsafe_code)] 3 | #![deny(warnings)] 4 | //! This crate contain anything related to routing for the `leptos_i18n` crate. 5 | 6 | mod components; 7 | mod routing; 8 | 9 | pub use components::I18nRoute; 10 | 11 | /// Create a route segment that is possible to define based on a locale. 12 | /// 13 | /// ```rust, ignore 14 | /// 15 | /// ``` 16 | #[macro_export] 17 | macro_rules! i18n_path { 18 | ($t:ty, $func:expr) => {{ 19 | $crate::__private::make_i18n_segment::<$t, _>($func) 20 | }}; 21 | } 22 | 23 | #[doc(hidden)] 24 | pub mod __private { 25 | pub use crate::routing::make_i18n_segment; 26 | } 27 | -------------------------------------------------------------------------------- /tests/common/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "tests_common" 4 | version = "0.1.0" 5 | edition = "2021" 6 | 7 | [lib] 8 | crate-type = ["cdylib", "rlib"] 9 | 10 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 11 | 12 | [dependencies] 13 | leptos = { workspace = true } 14 | -------------------------------------------------------------------------------- /tests/json/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode -------------------------------------------------------------------------------- /tests/json/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /tests/json/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /tests/json/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /tests/json/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "json" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib", "rlib"] 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | leptos = { workspace = true, features = ["ssr"] } 13 | tests_common = { workspace = true } 14 | 15 | [dependencies.leptos_i18n] 16 | workspace = true 17 | features = [ 18 | "json_files", 19 | "icu_compiled_data", 20 | "interpolate_display", 21 | "track_locale_files", 22 | "plurals", 23 | "format_datetime", 24 | "format_nums", 25 | "format_list", 26 | "format_currency", 27 | ] 28 | 29 | 30 | [package.metadata.leptos-i18n] 31 | default = "en" 32 | locales = ["en", "fr"] 33 | -------------------------------------------------------------------------------- /tests/json/README.md: -------------------------------------------------------------------------------- 1 | # JSON files format tests 2 | 3 | Test 2 things: 4 | 5 | - Everything compile fine 6 | - Check if the output is correct 7 | -------------------------------------------------------------------------------- /tests/json/src/defaulted.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use tests_common::*; 3 | 4 | #[test] 5 | fn defaulted_string() { 6 | let en = td!(Locale::en, defaulted_string); 7 | assert_eq_rendered!(en, "this string is declared in locale en"); 8 | let fr = td!(Locale::fr, defaulted_string); 9 | assert_eq_rendered!(fr, "this string is declared in locale en"); 10 | } 11 | 12 | #[test] 13 | fn defaulted_interpolation() { 14 | let en = td!(Locale::en, defaulted_interpolation, locale = "en"); 15 | assert_eq_rendered!(en, "this interpolation is declared in locale en"); 16 | let fr = td!(Locale::fr, defaulted_interpolation, locale = "en"); 17 | assert_eq_rendered!(fr, "this interpolation is declared in locale en"); 18 | } 19 | 20 | #[test] 21 | fn defaulted_ranges() { 22 | let count = || 0; 23 | let en = td!(Locale::en, defaulted_ranges, locale = "en", count); 24 | assert_eq_rendered!(en, "zero"); 25 | let fr = td!(Locale::fr, defaulted_ranges, locale = "en", count); 26 | assert_eq_rendered!(fr, "zero"); 27 | 28 | for i in [-3, 5, 12] { 29 | let count = move || i; 30 | let en = td!(Locale::en, defaulted_ranges, locale = "en", count); 31 | assert_eq_rendered!(en, "this range is declared in locale en"); 32 | let fr = td!(Locale::fr, defaulted_ranges, locale = "en", count); 33 | assert_eq_rendered!(fr, "this range is declared in locale en"); 34 | } 35 | } 36 | 37 | #[test] 38 | fn defaulted_foreign_key() { 39 | let en = td!(Locale::en, defaulted_foreign_key); 40 | assert_eq_rendered!(en, "before Click to increment the counter after"); 41 | let fr = td!(Locale::fr, defaulted_foreign_key); 42 | assert_eq_rendered!(fr, "before Click to increment the counter after"); 43 | } 44 | 45 | #[test] 46 | fn defaulted_subkeys() { 47 | let en = td!(Locale::en, defaulted_subkeys.subkey); 48 | assert_eq_rendered!(en, "some string"); 49 | let fr = td!(Locale::fr, defaulted_subkeys.subkey); 50 | assert_eq_rendered!(fr, "some string"); 51 | } 52 | -------------------------------------------------------------------------------- /tests/json/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | leptos_i18n::load_locales!(); 4 | 5 | #[cfg(test)] 6 | mod defaulted; 7 | #[cfg(test)] 8 | mod foreign; 9 | #[cfg(test)] 10 | mod formatting; 11 | #[cfg(test)] 12 | mod plurals; 13 | #[cfg(test)] 14 | mod ranges; 15 | #[cfg(test)] 16 | mod scoped; 17 | #[cfg(test)] 18 | mod subkeys; 19 | #[cfg(test)] 20 | mod tests; 21 | 22 | #[cfg(test)] 23 | mod t_format; 24 | #[cfg(test)] 25 | mod t_plural; 26 | -------------------------------------------------------------------------------- /tests/json/src/scoped.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use tests_common::*; 3 | 4 | #[test] 5 | fn subkey_3() { 6 | let en_scope = scope_locale!(Locale::en, subkeys); 7 | let fr_scope = scope_locale!(Locale::fr, subkeys); 8 | 9 | let count = || 0; 10 | let en = td!(en_scope, subkey_3, count); 11 | assert_eq_rendered!(en, "zero"); 12 | let fr = td!(fr_scope, subkey_3, count); 13 | assert_eq_rendered!(fr, "0"); 14 | let count = || 1; 15 | let en = td!(en_scope, subkey_3, count); 16 | assert_eq_rendered!(en, "one"); 17 | let fr = td!(fr_scope, subkey_3, count); 18 | assert_eq_rendered!(fr, "1"); 19 | let count = || 3; 20 | let en = td!(en_scope, subkey_3, count); 21 | assert_eq_rendered!(en, "3"); 22 | let fr = td!(fr_scope, subkey_3, count); 23 | assert_eq_rendered!(fr, "3"); 24 | } 25 | -------------------------------------------------------------------------------- /tests/json5/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode -------------------------------------------------------------------------------- /tests/json5/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /tests/json5/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /tests/json5/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /tests/json5/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "json5" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib", "rlib"] 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | leptos = { version = "0.7.0", features = ["ssr"] } 13 | tests_common = { path = "../common" } 14 | leptos_i18n = { path = "../../leptos_i18n", default-features = false, features = [ 15 | "json5_files", 16 | "icu_compiled_data", 17 | "track_locale_files", 18 | ] } 19 | 20 | 21 | [package.metadata.leptos-i18n] 22 | default = "en" 23 | locales = ["en", "fr"] 24 | -------------------------------------------------------------------------------- /tests/json5/README.md: -------------------------------------------------------------------------------- 1 | # YAML files format tests 2 | 3 | Test 2 things: 4 | 5 | - Everything compile fine 6 | - Check if the output is correct 7 | 8 | Disclaimer: the yaml files are slightly tweaked "JSON to YAML" outputs, if it looks ugly it's because it's only 3.14% hand made. 9 | -------------------------------------------------------------------------------- /tests/json5/locales/en.json5: -------------------------------------------------------------------------------- 1 | { 2 | click_to_change_lang: "Click to change language", 3 | click_count: "You clicked {{ count }} times", 4 | click_to_inc: "Click to increment the counter", 5 | f32_range: [ 6 | "f32", 7 | ["You are broke", 0.0], 8 | ["You owe money", "..0.0"], 9 | ["You have {{ count }}€"], 10 | ], 11 | u32_range: ["u32", [0, 0], ["1..", "1.."]], 12 | OR_range: [ 13 | "u8", 14 | ["0 or 5", "0", 5], 15 | ["1..5 | 6..10", "1..5", "6..10"], 16 | ["10..15 | 20", "10..15", 20], 17 | ["fallback with no count"], 18 | ], 19 | f32_OR_range: [ 20 | "f32", 21 | ["0 or 5", 0, 5], 22 | ["1..5 | 6..10", "1..5", "6..10"], 23 | ["10..15 | 20", "10..15", 20], 24 | ["fallback with no count"], 25 | ], 26 | subkeys: { 27 | subkey_1: "subkey_1", 28 | subkey_2: "subkey_2", 29 | subkey_3: [ 30 | ["zero", 0], 31 | ["one", 1], 32 | ["{{ count }}", "_"], 33 | ], 34 | }, 35 | defaulted_string: "this string is declared in locale en", 36 | defaulted_interpolation: "this interpolation is declared in locale {{ locale }}", 37 | defaulted_ranges: [ 38 | ["zero", 0], 39 | ["this range is declared in locale {{ locale }}"], 40 | ], 41 | } 42 | -------------------------------------------------------------------------------- /tests/json5/locales/fr.json5: -------------------------------------------------------------------------------- 1 | { 2 | click_to_change_lang: "Cliquez pour changez de langue", 3 | click_count: "Vous avez cliqué {{ count }} fois", 4 | click_to_inc: "Cliquez pour incrémenter le compteur", 5 | f32_range: [ 6 | "f32", 7 | ["Vous êtes pauvre", 0.0], 8 | ["Vous devez de l'argent", "..0.0"], 9 | ["Vous avez {{ count }}€"], 10 | ], 11 | u32_range: ["u32", [0, 0], ["1..", "1.."]], 12 | OR_range: [ 13 | "u8", 14 | ["0 or 5", "0", 5], 15 | ["1..5 | 6..10", "1..5", "6..10"], 16 | ["10..15 | 20", "10..15", 20], 17 | ["fallback sans count"], 18 | ], 19 | f32_OR_range: [ 20 | "f32", 21 | ["0 or 5", 0, 5], 22 | ["1..5 | 6..10", "1..5", "6..10"], 23 | ["10..15 | 20", "10..15", 20], 24 | ["fallback avec tuple vide", []], 25 | ], 26 | subkeys: { 27 | subkey_1: "subkey_1", 28 | subkey_2: "subkey_2", 29 | subkey_3: [ 30 | ["0", 0], 31 | ["{{ count }}", "_"], 32 | ], 33 | }, 34 | defaulted_string: null, 35 | defaulted_interpolation: null, 36 | defaulted_ranges: null, 37 | } 38 | -------------------------------------------------------------------------------- /tests/json5/src/defaulted.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use tests_common::*; 3 | 4 | #[test] 5 | fn defaulted_string() { 6 | let en = td!(Locale::en, defaulted_string); 7 | assert_eq_rendered!(en, "this string is declared in locale en"); 8 | let fr = td!(Locale::fr, defaulted_string); 9 | assert_eq_rendered!(fr, "this string is declared in locale en"); 10 | } 11 | 12 | #[test] 13 | fn defaulted_interpolation() { 14 | let en = td!(Locale::en, defaulted_interpolation, locale = "en"); 15 | assert_eq_rendered!(en, "this interpolation is declared in locale en"); 16 | let fr = td!(Locale::fr, defaulted_interpolation, locale = "en"); 17 | assert_eq_rendered!(fr, "this interpolation is declared in locale en"); 18 | } 19 | 20 | #[test] 21 | fn defaulted_ranges() { 22 | let count = || 0; 23 | let en = td!(Locale::en, defaulted_ranges, locale = "en", count = count); 24 | assert_eq_rendered!(en, "zero"); 25 | let fr = td!(Locale::fr, defaulted_ranges, locale = "en", count = count); 26 | assert_eq_rendered!(fr, "zero"); 27 | 28 | for i in [-3, 5, 12] { 29 | let count = move || i; 30 | let en = td!(Locale::en, defaulted_ranges, locale = "en", count = count); 31 | assert_eq_rendered!(en, "this range is declared in locale en"); 32 | let fr = td!(Locale::fr, defaulted_ranges, locale = "en", count = count); 33 | assert_eq_rendered!(fr, "this range is declared in locale en"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/json5/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | leptos_i18n::load_locales!(); 3 | 4 | #[cfg(test)] 5 | mod ranges; 6 | 7 | #[cfg(test)] 8 | mod subkeys; 9 | 10 | #[cfg(test)] 11 | mod tests; 12 | 13 | #[cfg(test)] 14 | mod defaulted; 15 | -------------------------------------------------------------------------------- /tests/json5/src/subkeys.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use tests_common::*; 3 | 4 | #[test] 5 | fn subkey_1() { 6 | let en = td!(Locale::en, subkeys.subkey_1); 7 | assert_eq_rendered!(en, "subkey_1"); 8 | let fr = td!(Locale::fr, subkeys.subkey_1); 9 | assert_eq_rendered!(fr, "subkey_1"); 10 | } 11 | 12 | #[test] 13 | fn subkey_2() { 14 | let b = |children: ChildrenFn| view! { {move || children()} }; 15 | let en = td!(Locale::en, subkeys.subkey_2, ); 16 | assert_eq_rendered!(en, "subkey_2"); 17 | let fr = td!(Locale::fr, subkeys.subkey_2, ); 18 | assert_eq_rendered!(fr, "subkey_2"); 19 | 20 | let b = |children: ChildrenFn| view! {
"before "{move || children()}" after"
}; 21 | let en = td!(Locale::en, subkeys.subkey_2, ); 22 | assert_eq_rendered!(en, "
before subkey_2 after
"); 23 | let fr = td!(Locale::fr, subkeys.subkey_2, ); 24 | assert_eq_rendered!(fr, "
before subkey_2 after
"); 25 | } 26 | 27 | #[test] 28 | fn subkey_3() { 29 | let count = || 0; 30 | let en = td!(Locale::en, subkeys.subkey_3, count = count); 31 | assert_eq_rendered!(en, "zero"); 32 | let fr = td!(Locale::fr, subkeys.subkey_3, count = count); 33 | assert_eq_rendered!(fr, "0"); 34 | let count = || 1; 35 | let en = td!(Locale::en, subkeys.subkey_3, count = count); 36 | assert_eq_rendered!(en, "one"); 37 | let fr = td!(Locale::fr, subkeys.subkey_3, count = count); 38 | assert_eq_rendered!(fr, "1"); 39 | let count = || 3; 40 | let en = td!(Locale::en, subkeys.subkey_3, count = count); 41 | assert_eq_rendered!(en, "3"); 42 | let fr = td!(Locale::fr, subkeys.subkey_3, count = count); 43 | assert_eq_rendered!(fr, "3"); 44 | } 45 | -------------------------------------------------------------------------------- /tests/namespaces/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode -------------------------------------------------------------------------------- /tests/namespaces/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /tests/namespaces/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /tests/namespaces/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales", 4 | "i18n-ally.namespace": true 5 | } -------------------------------------------------------------------------------- /tests/namespaces/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "namespaces" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib", "rlib"] 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | leptos = { workspace = true, features = ["ssr"] } 13 | tests_common = { workspace = true } 14 | 15 | [dependencies.leptos_i18n] 16 | workspace = true 17 | features = [ 18 | "json_files", 19 | "icu_compiled_data", 20 | "interpolate_display", 21 | "track_locale_files", 22 | ] 23 | 24 | 25 | [package.metadata.leptos-i18n] 26 | default = "en" 27 | locales = ["en", "fr"] 28 | namespaces = ["first_namespace", "second_namespace"] 29 | -------------------------------------------------------------------------------- /tests/namespaces/README.md: -------------------------------------------------------------------------------- 1 | # Namespaces test 2 | 3 | Test 2 things: 4 | 5 | - Everything compile fine 6 | - Check if the output is correct 7 | -------------------------------------------------------------------------------- /tests/namespaces/locales/en/first_namespace.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Click to change language", 3 | "common_key": "first namespace", 4 | "range_only_en": [ 5 | { 6 | "count": 0, 7 | "value": "exact" 8 | }, 9 | { 10 | "count": "..0", 11 | "value": "unbounded start" 12 | }, 13 | { 14 | "count": "99..", 15 | "value": "unbounded end" 16 | }, 17 | { 18 | "count": "1..3", 19 | "value": "excluded end" 20 | }, 21 | { 22 | "count": "3..=8", 23 | "value": "included end" 24 | }, 25 | { 26 | "count": "_", 27 | "value": "fallback" 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /tests/namespaces/locales/en/second_namespace.json: -------------------------------------------------------------------------------- 1 | { 2 | "common_key": "second namespace", 3 | "click_count": "You clicked {{ count }} times", 4 | "click_to_inc": "Click to increment the counter", 5 | "subkeys": { 6 | "subkey_1": "subkey_1", 7 | "subkey_2": "subkey_2", 8 | "subkey_3": [ 9 | ["zero", "0"], 10 | ["one", 1], 11 | ["{{ count }}", "_"] 12 | ] 13 | }, 14 | "foreign_key_to_same_namespace": "before $t(second_namespace:common_key) after", 15 | "foreign_key_to_another_namespace": "before $t(first_namespace:common_key) after" 16 | } 17 | -------------------------------------------------------------------------------- /tests/namespaces/locales/fr/first_namespace.json: -------------------------------------------------------------------------------- 1 | { 2 | "click_to_change_lang": "Cliquez pour changez de langue", 3 | "common_key": "premier namespace", 4 | "range_only_en": "pas de ranges en français" 5 | } 6 | -------------------------------------------------------------------------------- /tests/namespaces/locales/fr/second_namespace.json: -------------------------------------------------------------------------------- 1 | { 2 | "common_key": "deuxième namespace", 3 | "click_count": "Vous avez cliqué {{ count }} fois", 4 | "click_to_inc": "Cliquez pour incrémenter le compteur", 5 | "subkeys": { 6 | "subkey_1": "subkey_1", 7 | "subkey_2": "subkey_2", 8 | "subkey_3": [ 9 | ["zero", 0], 10 | ["{{ count }}", "_"] 11 | ] 12 | }, 13 | "foreign_key_to_same_namespace": "before $t(second_namespace:common_key) after", 14 | "foreign_key_to_another_namespace": "before $t(first_namespace:common_key) after" 15 | } 16 | -------------------------------------------------------------------------------- /tests/namespaces/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | leptos_i18n::load_locales!(); 3 | 4 | #[cfg(test)] 5 | mod first_ns; 6 | #[cfg(test)] 7 | mod scoped; 8 | #[cfg(test)] 9 | mod second_ns; 10 | -------------------------------------------------------------------------------- /tests/yaml/.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | !.vscode -------------------------------------------------------------------------------- /tests/yaml/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "lokalise.i18n-ally", 4 | ] 5 | } -------------------------------------------------------------------------------- /tests/yaml/.vscode/i18n-ally-custom-framework.yml: -------------------------------------------------------------------------------- 1 | languageIds: 2 | - rust 3 | 4 | usageMatchRegex: 5 | - "[^\\w\\d]t!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 6 | - "[^\\w\\d]td!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 7 | - "[^\\w\\d]td_string!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 8 | - "[^\\w\\d]td_display!\\(\\s*[\\w.:]*,\\s*([\\w.]*)" 9 | 10 | monopoly: true 11 | -------------------------------------------------------------------------------- /tests/yaml/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "i18n-ally.keystyle": "nested", 3 | "i18n-ally.localesPaths": "locales" 4 | } -------------------------------------------------------------------------------- /tests/yaml/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "yaml" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [lib] 7 | crate-type = ["cdylib", "rlib"] 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [dependencies] 12 | leptos = { version = "0.7.0", features = ["ssr"] } 13 | tests_common = { path = "../common" } 14 | leptos_i18n = { path = "../../leptos_i18n", default-features = false, features = [ 15 | "yaml_files", 16 | "icu_compiled_data", 17 | "track_locale_files", 18 | ] } 19 | 20 | 21 | [package.metadata.leptos-i18n] 22 | default = "en" 23 | locales = ["en", "fr"] 24 | -------------------------------------------------------------------------------- /tests/yaml/README.md: -------------------------------------------------------------------------------- 1 | # YAML files format tests 2 | 3 | Test 2 things: 4 | 5 | - Everything compile fine 6 | - Check if the output is correct 7 | 8 | Disclaimer: the yaml files are slightly tweaked "JSON to YAML" outputs, if it looks ugly it's because it's only 3.14% hand made. 9 | -------------------------------------------------------------------------------- /tests/yaml/locales/en.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | click_to_change_lang: Click to change language 3 | click_count: You clicked {{ count }} times 4 | click_to_inc: Click to increment the counter 5 | f32_range: 6 | - f32 7 | - count: "0.0" 8 | value: You are broke 9 | - count: "..0.0" 10 | value: You owe money 11 | - ["You have {{ count }}€", _] 12 | u32_range: 13 | - u32 14 | - count: 0 15 | value: "0" 16 | - count: 1.. 17 | value: 1.. 18 | OR_range: 19 | - u8 20 | - [0 or 5, "0", 5] 21 | - count: 1..5 | 6..10 22 | value: 1..5 | 6..10 23 | - count: 24 | - 10..15 25 | - "20" 26 | value: 10..15 | 20 27 | - value: fallback with no count 28 | f32_OR_range: 29 | - f32 30 | - count: 0 | 5 31 | value: 0 or 5 32 | - count: 33 | - 1..5 34 | - 6..10 35 | value: 1..5 | 6..10 36 | - count: 37 | - 10..15 | 20 38 | value: 10..15 | 20 39 | - - fallback with no count 40 | subkeys: 41 | subkey_1: subkey_1 42 | subkey_2: "subkey_2" 43 | subkey_3: 44 | - [zero, 0] 45 | - [one, 1] 46 | - ["{{ count }}", _] 47 | defaulted_string: this string is declared in locale en 48 | defaulted_interpolation: this interpolation is declared in locale {{ locale }} 49 | defaulted_ranges: 50 | - [zero, 0] 51 | - - this range is declared in locale {{ locale }} 52 | -------------------------------------------------------------------------------- /tests/yaml/locales/fr.yml: -------------------------------------------------------------------------------- 1 | click_to_change_lang: Cliquez pour changez de langue 2 | click_count: Vous avez cliqué {{ count }} fois 3 | click_to_inc: Cliquez pour incrémenter le compteur 4 | f32_range: 5 | - f32 6 | - count: 0 7 | value: Vous êtes pauvre 8 | - count: ..0.0 9 | value: Vous devez de l'argent 10 | - count: _ 11 | value: Vous avez {{ count }}€ 12 | u32_range: 13 | - u32 14 | - count: 0 15 | value: "0" 16 | - count: 1.. 17 | value: 1.. 18 | OR_range: 19 | - u8 20 | - count: 0 | 5 21 | value: 0 or 5 22 | - count: 1..5 | 6..10 23 | value: 1..5 | 6..10 24 | - count: 25 | - 10..15 26 | - 20 27 | value: 10..15 | 20 28 | - value: fallback sans count 29 | f32_OR_range: 30 | - f32 31 | - ["0 or 5", [0, "5"]] 32 | - count: 33 | - 1..5 34 | - 6..10 35 | value: 1..5 | 6..10 36 | - count: 37 | - 10..15 | 20 38 | value: 10..15 | 20 39 | - count: [] 40 | value: fallback avec tuple vide 41 | subkeys: 42 | subkey_1: subkey_1 43 | subkey_2: subkey_2 44 | subkey_3: 45 | - ["0", 0] 46 | - ["{{ count }}", _] 47 | defaulted_string: 48 | defaulted_interpolation: ~ 49 | defaulted_ranges: null 50 | -------------------------------------------------------------------------------- /tests/yaml/src/defaulted.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use tests_common::*; 3 | 4 | #[test] 5 | fn defaulted_string() { 6 | let en = td!(Locale::en, defaulted_string); 7 | assert_eq_rendered!(en, "this string is declared in locale en"); 8 | let fr = td!(Locale::fr, defaulted_string); 9 | assert_eq_rendered!(fr, "this string is declared in locale en"); 10 | } 11 | 12 | #[test] 13 | fn defaulted_interpolation() { 14 | let en = td!(Locale::en, defaulted_interpolation, locale = "en"); 15 | assert_eq_rendered!(en, "this interpolation is declared in locale en"); 16 | let fr = td!(Locale::fr, defaulted_interpolation, locale = "en"); 17 | assert_eq_rendered!(fr, "this interpolation is declared in locale en"); 18 | } 19 | 20 | #[test] 21 | fn defaulted_ranges() { 22 | let count = || 0; 23 | let en = td!(Locale::en, defaulted_ranges, locale = "en", count = count); 24 | assert_eq_rendered!(en, "zero"); 25 | let fr = td!(Locale::fr, defaulted_ranges, locale = "en", count = count); 26 | assert_eq_rendered!(fr, "zero"); 27 | 28 | for i in [-3, 5, 12] { 29 | let count = move || i; 30 | let en = td!(Locale::en, defaulted_ranges, locale = "en", count = count); 31 | assert_eq_rendered!(en, "this range is declared in locale en"); 32 | let fr = td!(Locale::fr, defaulted_ranges, locale = "en", count = count); 33 | assert_eq_rendered!(fr, "this range is declared in locale en"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/yaml/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | leptos_i18n::load_locales!(); 3 | 4 | #[cfg(test)] 5 | mod ranges; 6 | 7 | #[cfg(test)] 8 | mod subkeys; 9 | 10 | #[cfg(test)] 11 | mod tests; 12 | 13 | #[cfg(test)] 14 | mod defaulted; 15 | -------------------------------------------------------------------------------- /tests/yaml/src/subkeys.rs: -------------------------------------------------------------------------------- 1 | use crate::i18n::*; 2 | use tests_common::*; 3 | 4 | #[test] 5 | fn subkey_1() { 6 | let en = td!(Locale::en, subkeys.subkey_1); 7 | assert_eq_rendered!(en, "subkey_1"); 8 | let fr = td!(Locale::fr, subkeys.subkey_1); 9 | assert_eq_rendered!(fr, "subkey_1"); 10 | } 11 | 12 | #[test] 13 | fn subkey_2() { 14 | let b = |children: ChildrenFn| view! { {move || children()} }; 15 | let en = td!(Locale::en, subkeys.subkey_2, ); 16 | assert_eq_rendered!(en, "subkey_2"); 17 | let fr = td!(Locale::fr, subkeys.subkey_2, ); 18 | assert_eq_rendered!(fr, "subkey_2"); 19 | 20 | let b = |children: ChildrenFn| view! {
"before "{move || children()}" after"
}; 21 | let en = td!(Locale::en, subkeys.subkey_2, ); 22 | assert_eq_rendered!(en, "
before subkey_2 after
"); 23 | let fr = td!(Locale::fr, subkeys.subkey_2, ); 24 | assert_eq_rendered!(fr, "
before subkey_2 after
"); 25 | } 26 | 27 | #[test] 28 | fn subkey_3() { 29 | let count = || 0; 30 | let en = td!(Locale::en, subkeys.subkey_3, count = count); 31 | assert_eq_rendered!(en, "zero"); 32 | let fr = td!(Locale::fr, subkeys.subkey_3, count = count); 33 | assert_eq_rendered!(fr, "0"); 34 | let count = || 1; 35 | let en = td!(Locale::en, subkeys.subkey_3, count = count); 36 | assert_eq_rendered!(en, "one"); 37 | let fr = td!(Locale::fr, subkeys.subkey_3, count = count); 38 | assert_eq_rendered!(fr, "1"); 39 | let count = || 3; 40 | let en = td!(Locale::en, subkeys.subkey_3, count = count); 41 | assert_eq_rendered!(en, "3"); 42 | let fr = td!(Locale::fr, subkeys.subkey_3, count = count); 43 | assert_eq_rendered!(fr, "3"); 44 | } 45 | --------------------------------------------------------------------------------