npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@deriv-com/translations

v1.3.9

Published

This is a localization library that uses `i18next`, `react-i18next`, and a custom OTA SDK for translations.

Downloads

9,399

Readme

@deriv-com/translations

This is a localization library that uses i18next, react-i18next, and a custom OTA SDK for translations.

In this document

Overview

image

Requirements

The stored translation directory must have the following structure: {{ BASE_URL }}/translations/{lang}.json

base_url is the cdnUrl passed to the initializeI18n function, and lang is the language code. Refer to the example

Getting Started

To get started, one would need few things to setup first which are:

  1. A Crowdin project which will be used to manage translations for your project.
  2. A Cloudflare R2 account to store the translations.
    • Create a new bucket in the R2 account.
    • Create a new access key in the R2 account.
  3. Add the following secrets to your repository:
    • CROWDIN_PROJECT_ID: Open your crowdin project and navigate to Tools tab, you will be able to get the Project ID, store that in your github secrets.
    • CROWDIN_PERSONAL_TOKEN: This can be obtained by logging in to your crowdin account and clicking on your profile icon and goto Settings > API and create a new personal access token, store that in your github secrets.
    • R2_ACCOUNT_ID: R2 account ID from the Cloudflare R2 dashboard.
    • R2_ACCESS_KEY_ID: R2 access key ID from the Cloudflare R2 dashboard.
    • R2_SECRET_ACCESS_KEY: R2 secret access key from the Cloudflare R2 dashboard.
    • R2_BUCKET_NAME: R2 bucket name from the Cloudflare R2 dashboard.
  4. Add the following environment variable in your repository:
    • PROJECT_NAME: Add project name in your environment variable which will be used for Cloudflare R2 folder name for translations.
    • CROWDIN_BRANCH_NAME: Add the branch name for your crowdin project to separate the translations based on environment, this needs to be put into the environment variable instead of secret because the consumer of the package needs it while defining the cdnUrl to access the translations.
  5. Setup the github action to sync the translations to the CDN, refer to the Syncing translations section for more details.

Install the package by running:

npm install @deriv-com/translations

Setup

  • initialize translations in main component by importing and calling initializeI18n outside of the component function.
  • pass the return value to the TranslationProvider component from @deriv-com/translations.
  • pass default language to the TranslationProvider component.
    import { initializeI18n, TranslationProvider } from '@deriv-com/translations';
    ...
    const i18nInstance = initializeI18n({ cdnUrl: 'https://cdn.example.com' })

    const App = () => {
        ...
        return (
            <TranslationProvider defaultLang={'EN'} i18nInstance={i18nInstance}>
                <App />
            </TranslationProvider>
        )
    }

Usage

initializeI18n

The initializeI18n function initializes the i18next instance with the OTA SDK, react-i18next, and a language detector. It takes an object with a cdnUrl property, which is the URL of the CDN where the translations are stored.

import initializeI18n from "@deriv-com/translations";

initializeI18n({ cdnUrl: "https://cdn.example.com" });
  • For strings use either localize(...) or <Localize />.

Localize component example:

import { Localize } from "@deriv-com/translations";

<Localize
  i18n_default_text="You cannot use your real money account with {{website_name}} at this time."
  values={{ website_name }}
/>;

localize example:

Note that the localize function will not get the update from i18n instance once there is any changes like resource loaded or language change. This localize function is not to be used to wrap strings in components and only suitable for util/mapper functions which would not cause issues with string not getting updated.

import { localize } from "@deriv-com/translations";

const getNotification = () => ({
  all: localize("all notifications"),
});

useTranslations Hook

The useTranslations hook is a custom hook that adds some more returned values on top of the useTranslation hook from react-i18next. It can be used to translate strings in your components, toggle the language of the app and see the current language etc.

Example usage:

import { useTranslations } from "@deriv-com/translations";

const MyComponent = () => {
  const { localize, switchLanguage, currentLang } = useTranslations();

  const handleLanguageChange = () => {
    switchLanguage(currentLang === "EN" ? "DE" : "EN");
  };

  return <p onClick={handleLanguageChange}>{localize("Change language")}</p>;
};

Syncing translations

There is a github action that syncs the translations from Crowdin to the CDN.

The action takes following inputs:

  • PROJECT_SOURCE_DIRECTORY: Source directory of your project by default it is src.
  • CROWDIN_BASE_PATH: Base path of the translations in the Crowdin project by default it is ..
  • CROWDIN_BASE_URL: Base URL of the CDN where the translations are stored, default is https://api.crowdin.com.
  • CROWDIN_BRANCH_NAME: Running on production, test or staging etc.
  • CROWDIN_PROJECT_ID: Crowdin project ID which can be found in the crowdin project settings.
  • CROWDIN_PERSONAL_TOKEN: Crowdin personal token which can be found in the crowdin account settings.
  • R2_ACCOUNT_ID: R2 account ID from the Cloudflare R2 dashboard.
  • R2_ACCESS_KEY_ID: R2 access key ID from the Cloudflare R2 dashboard.
  • R2_SECRET_ACCESS_KEY: R2 secret access key from the Cloudflare R2 dashboard.
  • R2_BUCKET_NAME: R2 bucket name from the Cloudflare R2 dashboard.

Refer to the action file here.

Example usage of the action in the workflow file:

Copy and paste the following workflow code in your repository in this path.github/workflows/sync_translations.yml.

name: Sync translations

on:
  push:
    branches:
      - 'main'
  schedule:
    - cron: '0 */12 * * *'

jobs:
  sync_translations:
    runs-on: ubuntu-latest
    steps:
      - name: Sync translations
        uses: deriv-com/translations/.github/actions/extract_and_sync_translations@main
        with:
          PROJECT_NAME: ${{ env.PROJECT_NAME }}
          CROWDIN_BRANCH_NAME: ${{ env.CROWDIN_BRANCH_NAME }}
          CROWDIN_BASE_URL: ${{ env.CROWDIN_BASE_URL }}
          CROWDIN_BASE_PATH: ${{ env.CROWDIN_BASE_PATH }}
          CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
          CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
          R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
          R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
          R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
          R2_BUCKET_NAME: ${{ secrets.R2_BUCKET_NAME }}

Contributing

Contributions are welcome. Please open a pull request with your changes.