Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/boot/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ const boot = async ( currentUser, registerRoutes ) => {
disablePersistHostingDashboardQueryClient();
clearHostingDashboardQueryClient();
} );
setupLocale( currentUser, reduxStore );
await setupLocale( currentUser, reduxStore );
setupCountryCode();
configureReduxStore( currentUser, reduxStore );
setupMiddlewares( currentUser, reduxStore, queryClient );
Expand Down
18 changes: 11 additions & 7 deletions client/boot/locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export function getLocaleFromQueryParam() {
return query.get( 'locale' );
}

export const setupLocale = ( currentUser, reduxStore ) => {
export const setupLocale = async ( currentUser, reduxStore ) => {
if ( config.isEnabled( 'i18n/empathy-mode' ) && currentUser.i18n_empathy_mode ) {
initLanguageEmpathyMode();
}
Expand All @@ -49,7 +49,7 @@ export const setupLocale = ( currentUser, reduxStore ) => {
i18n.setLocale( localeData );
const localeSlug = i18n.getLocaleSlug();
const localeVariant = i18n.getLocaleVariant();
reduxStore.dispatch( { type: LOCALE_SET, localeSlug, localeVariant } );
await reduxStore.dispatch( { type: LOCALE_SET, localeSlug, localeVariant } );
// Propagate the locale to @automattic/number-formatters
setLocaleNumberFormatters( localeVariant || localeSlug );

Expand All @@ -59,22 +59,26 @@ export const setupLocale = ( currentUser, reduxStore ) => {
} else if ( currentUser && currentUser.localeSlug ) {
if ( shouldUseFallbackLocale ) {
// Use user locale fallback slug
reduxStore.dispatch( setLocale( userLocaleSlug ) );
await reduxStore.dispatch( setLocale( userLocaleSlug ) );
} else {
// Use the current user's and load traslation data with a fetch request
reduxStore.dispatch( setLocale( currentUser.localeSlug, currentUser.localeVariant ) );
await reduxStore.dispatch( setLocale( currentUser.localeSlug, currentUser.localeVariant ) );
}
} else if ( bootstrappedLocaleSlug ) {
// Use locale slug from bootstrapped language manifest object
reduxStore.dispatch( setLocale( bootstrappedLocaleSlug ) );
await reduxStore.dispatch( setLocale( bootstrappedLocaleSlug ) );
} else if ( getLocaleFromQueryParam() ) {
// For logged out Calypso pages, set the locale from query param
const pathLocaleSlug = getLocaleFromQueryParam();
pathLocaleSlug && reduxStore.dispatch( setLocale( pathLocaleSlug, '' ) );
if ( pathLocaleSlug ) {
await reduxStore.dispatch( setLocale( pathLocaleSlug, '' ) );
}
} else if ( ! window.hasOwnProperty( 'localeFromRoute' ) ) {
// For logged out Calypso pages, set the locale from path if we cannot get the locale from the route on the server side
const pathLocaleSlug = getLocaleFromPathname();
pathLocaleSlug && reduxStore.dispatch( setLocale( pathLocaleSlug, '' ) );
if ( pathLocaleSlug ) {
await reduxStore.dispatch( setLocale( pathLocaleSlug, '' ) );
}
recordTracksEvent( 'calypso_locale_set', { path: window.location.pathname } );
}

Expand Down
11 changes: 9 additions & 2 deletions client/controller/test/shared.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { setLocale } from '../../state/ui/language/actions';
import { setLocaleMiddleware } from '../shared';

jest.mock( '../../state/ui/language/actions', () => ( {
setLocale: jest.fn( () => jest.fn() ),
} ) );

describe( 'setLocaleMiddleware', () => {
const next = jest.fn();
const dispatch = jest.fn();
Expand All @@ -10,6 +14,7 @@ describe( 'setLocaleMiddleware', () => {
beforeEach( () => {
next.mockClear();
dispatch.mockClear();
setLocale.mockClear();
context = { query: {}, params: {}, store: { dispatch } };
middleware = setLocaleMiddleware();
} );
Expand All @@ -25,7 +30,8 @@ describe( 'setLocaleMiddleware', () => {
middleware( context, next );
expect( next ).toHaveBeenCalledTimes( 1 );
expect( context.store.dispatch ).toHaveBeenCalledTimes( 1 );
expect( context.store.dispatch ).toHaveBeenCalledWith( setLocale( 'fr' ) );
expect( setLocale ).toHaveBeenCalledWith( 'fr' );
// expect( context.store.dispatch ).toHaveBeenCalledWith( setLocale( 'fr' ) );
expect( context.lang ).toEqual( 'fr' );
} );

Expand All @@ -34,7 +40,8 @@ describe( 'setLocaleMiddleware', () => {
middleware( context, next );
expect( next ).toHaveBeenCalledTimes( 1 );
expect( context.store.dispatch ).toHaveBeenCalledTimes( 1 );
expect( context.store.dispatch ).toHaveBeenCalledWith( setLocale( 'fr' ) );
expect( setLocale ).toHaveBeenCalledWith( 'fr' );
// expect( context.store.dispatch ).toHaveBeenCalledWith( setLocale( 'fr' ) );
expect( context.lang ).toEqual( 'fr' );
} );
} );
43 changes: 22 additions & 21 deletions client/lib/i18n-utils/switch-locale.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { captureException } from '@automattic/calypso-sentry';
import { getUrlFromParts, getUrlParts } from '@automattic/calypso-url';
import { isDefaultLocale, getLanguage } from '@automattic/i18n-utils';
import { setLocale as setLocaleNumberFormatters } from '@automattic/number-formatters';
import { defaultI18n } from '@wordpress/i18n';
import debugFactory from 'debug';
import i18n from 'i18n-calypso';
import { forEach, throttle } from 'lodash';
Expand Down Expand Up @@ -370,6 +371,7 @@ export default async function switchLocale( localeSlug ) {
}

i18n.setLocale( locale );
defaultI18n.setLocaleData( i18n.getLocale() );
setLocaleInDOM();
removeRequireChunkTranslationsHandler();
addRequireChunkTranslationsHandler( localeSlug, { translatedChunks } );
Expand Down Expand Up @@ -423,28 +425,27 @@ export default async function switchLocale( localeSlug ) {
debug( error );
}
} else {
getLanguageFile( localeSlug ).then(
// Success.
( body ) => {
if ( body ) {
// Handle race condition when we're requested to switch to a different
// locale while we're in the middle of request, we should abandon result
if ( localeSlug !== lastRequestedLocale ) {
return;
}

i18n.setLocale( body );
setLocaleInDOM();
loadUserUndeployedTranslations( localeSlug );
}
},
// Failure.
() => {
debug(
`Encountered an error loading locale file for ${ localeSlug }. Falling back to English.`
);
try {
const body = await getLanguageFile( localeSlug );
if ( ! body ) {
return;
}
);

// Handle race condition when we're requested to switch to a different
// locale while we're in the middle of request, we should abandon result
if ( localeSlug !== lastRequestedLocale ) {
return;
}

i18n.setLocale( body );
defaultI18n.setLocaleData( i18n.getLocale() );
setLocaleInDOM();
loadUserUndeployedTranslations( localeSlug );
} catch ( error ) {
debug(
`Encountered an error ${ error } loading locale file for ${ localeSlug }. Falling back to English.`
);
}
}
}

Expand Down
16 changes: 8 additions & 8 deletions client/state/ui/language/actions.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import switchLocale from 'calypso/lib/i18n-utils/switch-locale';
import { LOCALE_SET } from 'calypso/state/action-types';
import type { CalypsoDispatch } from 'calypso/state/types';

import 'calypso/state/ui/init';

Expand All @@ -11,13 +12,12 @@ export const setLocale = (
localeVariant: string | null | undefined = null
) => {
const newLocale = localeVariant || localeSlug;

// Side effect: change the current translation locale.
switchLocale( newLocale );

return {
type: LOCALE_SET,
localeSlug,
localeVariant,
return async ( dispatch: CalypsoDispatch ) => {
await switchLocale( newLocale );
dispatch( {
type: LOCALE_SET,
localeSlug,
localeVariant,
} );
};
};
18 changes: 14 additions & 4 deletions client/state/ui/language/test/actions.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import configureStore from 'redux-mock-store';
import { thunk } from 'redux-thunk';
import { LOCALE_SET } from 'calypso/state/action-types';
import { setLocale } from '../actions';

describe( 'actions', () => {
describe( 'setLocale', () => {
test( 'returns an appropriate action', () => {
expect( setLocale( 'he' ) ).toEqual( {
const middlewares = [ thunk ];
const mockStore = configureStore( middlewares );
test( 'dispatches an appropriate action', async () => {
const store = mockStore();
await store.dispatch( setLocale( 'he' ) );
const actions = store.getActions();
expect( actions[ 0 ] ).toEqual( {
type: LOCALE_SET,
localeSlug: 'he',
localeVariant: null,
} );
} );

test( 'returns an action with localeVariant set', () => {
expect( setLocale( 'he', 'he_formal' ) ).toEqual( {
test( 'dispatches an action with localeVariant set', async () => {
const store = mockStore();
await store.dispatch( setLocale( 'he', 'he_formal' ) );
const actions = store.getActions();
expect( actions[ 0 ] ).toEqual( {
type: LOCALE_SET,
localeSlug: 'he',
localeVariant: 'he_formal',
Expand Down