Skip to content

Commit

Permalink
[COJ]/likhith/COJ-1231/integrate deriv-translations in account-package (
Browse files Browse the repository at this point in the history
deriv-com#15448)

* chore: integrate deriv-tralstaions in account-package

* chore: integrated translation to account

* chore: rename ENV variables

* fix: failing testcae

* fix: translations for deriv-app

* fix: formatting of yml file

* chore: added a temp token

* chore: added a temp token

* chore: added a temp token

* Update .github/workflows/sync-translations.yml

* ci: add permission

* chore: synced translations

* chore: implemented sync b/w footer and account settings

* chore: added comments

* chore: updated package version

* chore: implemented translation lib changes to Deriv-app

* chore: implemented translation lib changes to Deriv-app

* chore: implemented translation lib changes to Deriv-app

* chore: updated deriv-com/translation

* chore: removed implemented TODOs

* fix: failing testcases

* fix: failing testcases

* fix: translation mock

* chore: incorporated review comments

* chore: added translation cache

* fix: caching pattern

* chore: reverted cache config

* fix: prettier issue

---------

Co-authored-by: Ali(Ako) Hosseini <[email protected]>
  • Loading branch information
likhith-deriv and ali-hosseini-deriv authored Jun 20, 2024
1 parent c476d10 commit 9fdfacb
Show file tree
Hide file tree
Showing 29 changed files with 177 additions and 61 deletions.
31 changes: 31 additions & 0 deletions .github/workflows/sync-translations.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Sync translations

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

jobs:
sync_translations:
permissions:
contents: write
runs-on: ubuntu-latest
environment: Staging
steps:
- name: Sync translations
uses: deriv-com/translations/.github/actions/extract_and_sync_translations@main
with:
PROJECT_NAME: ${{ vars.ACC_R2_PROJECT_NAME }}
CROWDIN_BRANCH_NAME: staging
CROWDIN_PROJECT_ID: ${{ secrets.ACC_CROWDIN_PROJECT_ID }}
CROWDIN_PERSONAL_TOKEN: ${{ secrets.ACC_CROWDIN_PERSONAL_TOKEN }}
R2_ACCOUNT_ID: ${{ secrets.ACC_R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.ACC_R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.ACC_R2_SECRET_ACCESS_KEY }}
R2_BUCKET_NAME: ${{ secrets.ACC_R2_BUCKET_NAME }}
PROJECT_SOURCE_DIRECTORY: "packages/account/src"
20 changes: 20 additions & 0 deletions __mocks__/translation.mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
const Localize = ({ i18n_default_text, values }) => {
// Replace placeholders in the default text with actual values
const localizedText = i18n_default_text.replace(/\{\{(\w+)\}\}/g, (match, key) => values[key] || match);

return localizedText || null;
};

// Mock for useTranslations hook
const useTranslations = () => ({
localize: jest.fn((text, args) => {
return text.replace(/{{(.*?)}}/g, (_, match) => args[match.trim()]);
}),
currentLang: 'EN',
});

const localize = jest.fn(text => text);

const getAllowedLanguages = jest.fn(() => ({ EN: 'English', VI: 'Tiếng Việt' }));

export { Localize, localize, useTranslations, getAllowedLanguages };
4 changes: 3 additions & 1 deletion jest.config.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ module.exports = {
coverageDirectory: './coverage/',
testRegex: '(/__tests__/.*|(\\.)(test|spec))\\.(js|jsx|tsx|ts)?$',
// This is needed to transform es modules imported from node_modules of the target component.
transformIgnorePatterns: ['/node_modules/(?!(@enykeev/react-virtualized|@simplewebauthn/browser)).+\\.js$'],
transformIgnorePatterns: [
'/node_modules/(?!(@enykeev/react-virtualized|@simplewebauthn/browser|@deriv-com/translations)).+\\.js$',
],
setupFiles: ['<rootDir>/../../jest.setup.js'],
setupFilesAfterEnv: ['<rootDir>/../../setupTests.js'],
testPathIgnorePatterns: ['/integration-tests/', '/component-tests/'],
Expand Down
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/account/build/constants.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const IgnorePlugin = require('webpack').IgnorePlugin;
const { IgnorePlugin } = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const path = require('path');
Expand Down
1 change: 1 addition & 0 deletions packages/account/build/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ module.exports = function (env) {
'@deriv/utils': '@deriv/utils',
'@deriv/quill-icons': `@deriv/quill-icons`,
'@deriv-com/utils': '@deriv-com/utils',
'@deriv-com/translations': '@deriv-com/translations',
},
/^@deriv\/shared\/.+$/,
/^@deriv\/components\/.+$/,
Expand Down
1 change: 1 addition & 0 deletions packages/account/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = {
moduleNameMapper: {
'\\.s(c|a)ss$': '<rootDir>/../../__mocks__/styleMock.js',
'^.+\\.svg$': '<rootDir>/../../__mocks__/styleMock.js',
'@deriv-com/translations': '<rootDir>/../../__mocks__/translation.mock.js',
'^Assets/(.*)$': '<rootDir>/src/Assets/$1',
'^Components/(.*)$': '<rootDir>/src/Components/$1',
'^Constants/(.*)$': '<rootDir>/src/Constants/$1',
Expand Down
2 changes: 1 addition & 1 deletion packages/account/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"dependencies": {
"@binary-com/binary-document-uploader": "^2.4.8",
"@deriv-com/analytics": "1.5.9",
"@deriv-com/translations": "^1.2.3",
"@deriv-com/translations": "^1.3.2",
"@deriv-com/utils": "^0.0.25",
"@deriv/api": "^1.0.0",
"@deriv/components": "^1.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import React, { Fragment } from 'react';
import { Formik, FormikValues, FormikHelpers, FormikErrors, Form } from 'formik';
import { Localize, localize } from '@deriv/translations';
import { GetSettings, ResidenceList } from '@deriv/api-types';
import { Button } from '@deriv/components';
import {
Expand All @@ -9,6 +8,7 @@ import {
removeEmptyPropertiesFromObject,
getIDVNotApplicableOption,
} from '@deriv/shared';
import { useTranslations, Localize } from '@deriv-com/translations';
import PoiNameDobExample from '../../../../Assets/ic-poi-name-dob-example.svg';
import FormSubHeader from '../../../form-sub-header';
import IDVForm from '../../../forms/idv-form';
Expand Down Expand Up @@ -43,6 +43,7 @@ export const IdvDocSubmitOnSignup = ({
getChangeableFields,
residence_list,
}: TIdvDocSubmitOnSignup) => {
const { localize } = useTranslations();
const side_note_image = <PoiNameDobExample />;
const validateFields = (values: TIDVDocFormType) => {
const errors: FormikErrors<Omit<TIDVDocFormType, 'document_type'> & { document_type?: string }> = {};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@ import userEvent from '@testing-library/user-event';
import { routes } from '@deriv/shared';
import LanguageSettings from '../language-settings';
import { mockStore, StoreProvider } from '@deriv/stores';
import { useTranslations } from '@deriv-com/translations';

jest.mock('@deriv-com/translations');

jest.mock('@deriv/shared', () => ({
...jest.requireActual('@deriv/shared'),
isMobile: jest.fn(() => false),
TranslationFlag: { lang_1: () => <div>Language 1 Flag</div>, lang_2: () => <div>Language 2 Flag</div> },
}));

jest.mock('@deriv/translations', () => ({
...jest.requireActual('@deriv/translations'),
getAllowedLanguages: jest.fn(() => ({ lang_1: 'Test Lang 1', lang_2: 'Test Lang 2' })),
TranslationFlag: { EN: () => <div>Language 1 Flag</div>, VI: () => <div>Language 2 Flag</div> },
}));

jest.mock('react-router-dom', () => ({
Expand All @@ -33,6 +31,11 @@ describe('LanguageSettings', () => {
is_mobile: false,
},
});
(useTranslations as jest.Mock).mockReturnValue({
currentLang: 'EN',
localize: jest.fn().mockImplementation(key => key),
switchLanguage: jest.fn(),
});
});

const renderLanguageSettings = () => {
Expand All @@ -46,20 +49,19 @@ describe('LanguageSettings', () => {

expect(screen.getByText('Select Language')).toBeInTheDocument();

const lang_1 = screen.getByText('Test Lang 1');
const lang_2 = screen.getByText('Test Lang 2');
const lang_1 = screen.getByText('English');
const lang_2 = screen.getByText('Tiếng Việt');

expect(screen.getByText(/Language 1 Flag/)).toBeInTheDocument();
expect(screen.getByText(/Language 2 Flag/)).toBeInTheDocument();
expect(lang_1).toBeInTheDocument();
expect(/(active)/i.test(lang_1.className)).toBeTruthy();
expect(lang_2).toBeInTheDocument();
expect(/(active)/i.test(lang_2.className)).toBeFalsy();
});

it('should trigger language change', () => {
renderLanguageSettings();

const lang_2 = screen.getByText('Test Lang 2');
const lang_2 = screen.getByText('Tiếng Việt');
userEvent.click(lang_2);

expect(mockRootStore.common.changeSelectedLanguage).toHaveBeenCalled();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import { Redirect } from 'react-router-dom';
import { routes } from '@deriv/shared';
import { UNSUPPORTED_LANGUAGES, routes } from '@deriv/shared';
import { observer, useStore } from '@deriv/stores';
import { localize, getAllowedLanguages } from '@deriv/translations';
import { useTranslations, getAllowedLanguages } from '@deriv-com/translations';
import FormSubHeader from '../../../Components/form-sub-header';
import LanguageRadioButton from '../../../Components/language-settings';
import { useEffect } from 'react';

const LanguageSettings = observer(() => {
const { client, common, ui } = useStore();
const { switchLanguage, currentLang, localize } = useTranslations();
const { has_wallet } = client;
// [TODO]: Remove changeSelectedLanguage() when whole app starts to use @deriv-com/translations
const { changeSelectedLanguage, current_language } = common;

const { is_mobile } = ui;

// [TODO]: Remove useEffect() when whole app starts to use @deriv-com/translations
// This is required to sync language state b/w footer language icon and Language settings
useEffect(() => {
switchLanguage(current_language);
}, [current_language, switchLanguage]);

if (is_mobile || has_wallet) {
return <Redirect to={routes.traders_hub} />;
}

const allowed_languages: Record<string, string> = getAllowedLanguages();
const allowed_languages: Record<string, string> = getAllowedLanguages(UNSUPPORTED_LANGUAGES);
return (
<div className='settings-language'>
<FormSubHeader title={localize('Select Language')} />
Expand All @@ -26,10 +36,13 @@ const LanguageSettings = observer(() => {
key={language_key}
id={language_key}
language_text={value}
is_current_language={current_language === language_key}
is_current_language={currentLang === language_key}
name='language-radio-group'
onChange={() => {
// [TODO]: Remove changeSelectedLanguage() when whole app starts to use @deriv-com/translations
// This function also helps in informing language change to BE
changeSelectedLanguage(language_key);
switchLanguage(language_key);
}}
/>
);
Expand Down
1 change: 1 addition & 0 deletions packages/appstore/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
moduleNameMapper: {
'\\.s(c|a)ss$': '<rootDir>/../../__mocks__/styleMock.js',
'^.+\\.svg$': '<rootDir>/../../__mocks__/fileMock.js',
'@deriv-com/translations': '<rootDir>/../../__mocks__/translation.mock.js',
'^Assets/(.*)$': '<rootDir>/src/assets/$1',
'^Components/(.*)$': '<rootDir>/src/components/$1',
'^Constants/(.*)$': '<rootDir>/src/constants/$1',
Expand Down
1 change: 1 addition & 0 deletions packages/appstore/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"license": "Apache-2.0",
"dependencies": {
"@deriv-com/analytics": "1.5.9",
"@deriv-com/translations": "^1.3.2",
"@deriv/account": "^1.0.0",
"@deriv/cashier": "^1.0.0",
"@deriv/cfd": "^1.0.0",
Expand Down
17 changes: 10 additions & 7 deletions packages/appstore/src/components/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,26 @@ import React from 'react';
import CashierStoreProvider from '@deriv/cashier/src/cashier-providers';
import CFDStoreProvider from '@deriv/cfd/src/cfd-providers';
import { StoreProvider } from '@deriv/stores';
import { TranslationProvider } from '@deriv-com/translations';
import AppContent from './app-content';
import './app.scss';

type TProps = {
passthrough: {
root_store: React.ComponentProps<typeof StoreProvider>['store'];
i18nInstance: Parameters<typeof TranslationProvider>[0]['i18nInstance'];
language: Exclude<Parameters<typeof TranslationProvider>[0]['defaultLang'], undefined>;
};
};

const App: React.FC<TProps> = ({ passthrough: { root_store } }) => (
<CashierStoreProvider store={root_store}>
<CFDStoreProvider store={root_store}>
<StoreProvider store={root_store}>
const App: React.FC<TProps> = ({ passthrough: { root_store, i18nInstance, language } }) => (
<TranslationProvider defaultLang={language} i18nInstance={i18nInstance}>
<CashierStoreProvider store={root_store}>
<CFDStoreProvider store={root_store}>
<AppContent />
</StoreProvider>
</CFDStoreProvider>
</CashierStoreProvider>
</CFDStoreProvider>
</CashierStoreProvider>
</TranslationProvider>
);

export default App;
1 change: 1 addition & 0 deletions packages/appstore/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ module.exports = function (env) {
'@deriv/cashier': true,
'@deriv/cfd': true,
'@deriv-com/analytics': `@deriv-com/analytics`,
'@deriv-com/translations': '@deriv-com/translations',
},
],
//TODO: Uncomment this line when type script migrations on all packages done
Expand Down
1 change: 1 addition & 0 deletions packages/cfd/build/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ module.exports = function (env) {
'@deriv/components': '@deriv/components',
'@deriv/translations': '@deriv/translations',
'@deriv/account': '@deriv/account',
'@deriv-com/translations': '@deriv-com/translations',
},
/^@deriv\/shared\/.+$/,
/^@deriv\/components\/.+$/,
Expand Down
1 change: 1 addition & 0 deletions packages/cfd/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
moduleNameMapper: {
'\\.s(c|a)ss$': '<rootDir>/../../__mocks__/styleMock.js',
'^.+\\.svg$': '<rootDir>/../../__mocks__/styleMock.js',
'@deriv-com/translations': '<rootDir>/../../__mocks__/translation.mock.js',
'^_common/(.*)$': '<rootDir>/src/_common/$1',
'^App/(.*)$': '<rootDir>/src/App/$1',
'^Assets/(.*)$': '<rootDir>/src/Assets/$1',
Expand Down
1 change: 1 addition & 0 deletions packages/cfd/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
},
"dependencies": {
"@deriv-com/analytics": "1.5.9",
"@deriv-com/translations": "^1.3.2",
"@deriv-com/utils": "^0.0.25",
"@deriv/account": "^1.0.0",
"@deriv/api": "^1.0.0",
Expand Down
5 changes: 3 additions & 2 deletions packages/core/build/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const CopyPlugin = require('copy-webpack-plugin');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const HtmlWebpackTagsPlugin = require('html-webpack-tags-plugin');
const PreloadWebpackPlugin = require('preload-webpack-plugin');
const IgnorePlugin = require('webpack').IgnorePlugin;
const { IgnorePlugin, DefinePlugin } = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const path = require('path');
Expand Down Expand Up @@ -33,7 +33,6 @@ const {
IS_RELEASE,
} = require('./loaders-config');
const Dotenv = require('dotenv-webpack');
const { DefinePlugin } = require('webpack');

const HOISTED_PACKAGES = {
react: path.resolve(__dirname, '../../../node_modules/react'),
Expand Down Expand Up @@ -139,6 +138,8 @@ const plugins = ({ base, is_test_env }) => {
'process.env.GROWTHBOOK_DECRYPTION_KEY': JSON.stringify(process.env.GROWTHBOOK_DECRYPTION_KEY),
'process.env.IS_GROWTHBOOK_ENABLED': JSON.stringify(process.env.IS_GROWTHBOOK_ENABLED),
'process.env.REMOTE_CONFIG_URL': JSON.stringify(process.env.REMOTE_CONFIG_URL),
'process.env.ACC_TRANSLATION_PATH': JSON.stringify('deriv-app-account/staging'),
'process.env.CROWDIN_URL': JSON.stringify('https://translations.deriv.com'),
}),
new CleanWebpackPlugin(),
new CopyPlugin(copyConfig(base)),
Expand Down
1 change: 1 addition & 0 deletions packages/core/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
moduleNameMapper: {
'\\.s(c|a)ss$': '<rootDir>/../../__mocks__/styleMock.js',
'^.+\\.svg$': '<rootDir>/../../__mocks__/styleMock.js',
'@deriv-com/translations': '<rootDir>/../../__mocks__/translation.mock.js',
'^_common/(.*)$': '<rootDir>/src/_common/$1',
'^App/(.*)$': '<rootDir>/src/App/$1',
'^Assets/(.*)$': '<rootDir>/src/Assets/$1',
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"@deriv-com/analytics": "1.5.9",
"@deriv-com/quill-tokens": "^2.0.4",
"@deriv-com/quill-ui": "^1.10.19",
"@deriv-com/translations": "^1.2.3",
"@deriv-com/translations": "^1.3.2",
"@deriv-com/utils": "^0.0.25",
"@deriv/account": "^1.0.0",
"@deriv/api": "^1.0.0",
Expand Down
Loading

0 comments on commit 9fdfacb

Please sign in to comment.