Skip to content

Commit

Permalink
Move localizeUrl to new i18n-utils package (#46998)
Browse files Browse the repository at this point in the history
Co-authored-by: Philip Jackson <[email protected]>
  • Loading branch information
lsl and p-jackson authored Nov 11, 2020
1 parent f863e91 commit 1446651
Show file tree
Hide file tree
Showing 14 changed files with 694 additions and 504 deletions.
384 changes: 8 additions & 376 deletions client/lib/i18n-utils/test/utils.js

Large diffs are not rendered by default.

130 changes: 2 additions & 128 deletions client/lib/i18n-utils/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import i18n, { getLocaleSlug } from 'i18n-calypso';
*/
import config from 'calypso/config';
import languages from '@automattic/languages';
import { getUrlParts, getUrlFromParts } from 'calypso/lib/url/url-parts';
import { getUrlParts } from 'calypso/lib/url/url-parts';
export { localizeUrl } from '@automattic/i18n-utils';

/**
* a locale can consist of three component
Expand Down Expand Up @@ -156,133 +157,6 @@ export function addLocaleToPath( path, locale ) {
return removeLocaleFromPath( urlParts.pathname ) + `/${ locale }` + queryString;
}

const localesWithBlog = [ 'en', 'ja', 'es', 'pt', 'fr', 'pt-br' ];
const localesWithPrivacyPolicy = [ 'en', 'fr', 'de' ];
const localesWithCookiePolicy = [ 'en', 'fr', 'de' ];
const localesToSubdomains = {
'pt-br': 'br',
br: 'bre',
zh: 'zh-cn',
'zh-hk': 'zh-tw',
'zh-sg': 'zh-cn',
kr: 'ko',
};

const setLocalizedUrlHost = ( hostname, validLocales = [] ) => ( urlParts, localeSlug ) => {
if ( typeof validLocales === 'string' ) {
validLocales = config( validLocales );
}

if ( validLocales.includes( localeSlug ) && localeSlug !== 'en' ) {
// Avoid changing the hostname when the locale is set via the path.
if ( urlParts.pathname.substr( 0, localeSlug.length + 2 ) !== '/' + localeSlug + '/' ) {
urlParts.host = `${ localesToSubdomains[ localeSlug ] || localeSlug }.${ hostname }`;
}
}
return urlParts;
};

const setLocalizedWpComPath = ( prefix, validLocales = [], limitPathMatch = null ) => (
urlParts,
localeSlug
) => {
urlParts.host = 'wordpress.com';
if (
typeof limitPathMatch === 'object' &&
limitPathMatch instanceof RegExp &&
! limitPathMatch.test( urlParts.pathname )
) {
validLocales = []; // only rewrite to English.
}
urlParts.pathname = prefix + urlParts.pathname;

if ( typeof validLocales === 'string' ) {
validLocales = config( validLocales );
}

if ( validLocales.includes( localeSlug ) && localeSlug !== 'en' ) {
urlParts.pathname = ( localesToSubdomains[ localeSlug ] || localeSlug ) + urlParts.pathname;
}
return urlParts;
};

const prefixLocalizedUrlPath = ( validLocales = [], limitPathMatch = null ) => (
urlParts,
localeSlug
) => {
if ( typeof validLocales === 'string' ) {
validLocales = config( validLocales );
}

if ( typeof limitPathMatch === 'object' && limitPathMatch instanceof RegExp ) {
if ( ! limitPathMatch.test( urlParts.pathname ) ) {
return urlParts; // No rewriting if not matches the path.
}
}

if ( validLocales.includes( localeSlug ) && localeSlug !== 'en' ) {
urlParts.pathname = ( localesToSubdomains[ localeSlug ] || localeSlug ) + urlParts.pathname;
}
return urlParts;
};

const urlLocalizationMapping = {
'wordpress.com/support/': prefixLocalizedUrlPath( 'support_site_locales' ),
'wordpress.com/blog/': prefixLocalizedUrlPath( localesWithBlog, /^\/blog\/?$/ ),
'wordpress.com/tos/': setLocalizedUrlHost( 'wordpress.com', 'magnificent_non_en_locales' ),
'jetpack.com': setLocalizedUrlHost( 'jetpack.com', 'jetpack_com_locales' ),
'en.support.wordpress.com': setLocalizedWpComPath( '/support', 'support_site_locales' ),
'en.blog.wordpress.com': setLocalizedWpComPath( '/blog', localesWithBlog, /^\/$/ ),
'en.forums.wordpress.com': setLocalizedUrlHost( 'forums.wordpress.com', 'forum_locales' ),
'automattic.com/privacy/': prefixLocalizedUrlPath( localesWithPrivacyPolicy ),
'automattic.com/cookies/': prefixLocalizedUrlPath( localesWithCookiePolicy ),
'wordpress.com': setLocalizedUrlHost( 'wordpress.com', 'magnificent_non_en_locales' ),
};

export function localizeUrl( fullUrl, locale ) {
const localeSlug = locale || ( typeof getLocaleSlug === 'function' ? getLocaleSlug() : 'en' );
const urlParts = getUrlParts( String( fullUrl ) );

if ( ! urlParts.host ) {
return fullUrl;
}

// Let's unify the URL.
urlParts.protocol = 'https:';
// Let's use `host` for everything.
delete urlParts.hostname;

if ( ! urlParts.pathname.endsWith( '.php' ) ) {
urlParts.pathname = ( urlParts.pathname + '/' ).replace( /\/+$/, '/' );
}

if ( ! localeSlug || 'en' === localeSlug ) {
if ( 'en.wordpress.com' === urlParts.host ) {
urlParts.host = 'wordpress.com';
return getUrlFromParts( urlParts ).href;
}
}

if ( 'en.wordpress.com' === urlParts.host ) {
urlParts.host = 'wordpress.com';
}

const lookup = [
urlParts.host,
urlParts.host + urlParts.pathname,
urlParts.host + urlParts.pathname.substr( 0, 1 + urlParts.pathname.indexOf( '/', 1 ) ),
];

for ( let i = lookup.length - 1; i >= 0; i-- ) {
if ( lookup[ i ] in urlLocalizationMapping ) {
return getUrlFromParts( urlLocalizationMapping[ lookup[ i ] ]( urlParts, localeSlug ) ).href;
}
}

// Nothing needed to be changed, just return it unmodified.
return fullUrl;
}

/**
* Removes the trailing locale slug from the path, if it is present.
* '/start/en' => '/start', '/start' => '/start', '/start/flow/fr' => '/start/flow', '/start/flow' => '/start/flow'
Expand Down
1 change: 1 addition & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@automattic/data-stores": "^1.0.0-alpha.1",
"@automattic/domain-picker": "^1.0.0-alpha.0",
"@automattic/format-currency": "^1.0.0-alpha.0",
"@automattic/i18n-utils": "^1.0.0",
"@automattic/languages": "^1.0.0",
"@automattic/language-picker": "^1.0.0",
"@automattic/lasagna": "^0.6.1",
Expand Down
2 changes: 2 additions & 0 deletions packages/i18n-calypso/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ declare namespace i18nCalypso {
) => TranslateResult;

export function registerTranslateHook( hook: TranslateHook ): void;

export function getLocaleSlug(): string | null;
}

export = i18nCalypso;
Expand Down
10 changes: 10 additions & 0 deletions packages/i18n-utils/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
overrides: [
{
files: [ '*.md.js' ],
rules: {
'import/no-extraneous-dependencies': 'off',
},
},
],
};
9 changes: 9 additions & 0 deletions packages/i18n-utils/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# I18n Utils

I18n-related utilities for use by client, server, apps, and packages.

## Usage

```js
import { localizeUrl } from '@automattic/i18n-utils';
```
3 changes: 3 additions & 0 deletions packages/i18n-utils/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
preset: '../../test/packages/jest-preset.js',
};
27 changes: 27 additions & 0 deletions packages/i18n-utils/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "@automattic/i18n-utils",
"version": "1.0.0",
"description": "WordPress.com i18n utils",
"main": "dist/cjs/index.js",
"module": "dist/esm/index.js",
"types": "dist/types/index.d.ts",
"sideEffects": false,
"license": "GPL-2.0-or-later",
"repository": {
"type": "git",
"url": "git+https://github.com/Automattic/wp-calypso.git",
"directory": "packages/i18n-utils"
},
"author": "Automattic Inc.",
"scripts": {
"clean": "npx rimraf dist",
"prepublish": "yarn run clean",
"prepare": "tsc --project ./tsconfig.json && tsc --project ./tsconfig-cjs.json",
"watch": "tsc --project ./tsconfig.json --watch",
"download": "node bin/download.js",
"test": "yarn jest"
},
"dependencies": {
"i18n-calypso": "^5.0.0"
}
}
1 change: 1 addition & 0 deletions packages/i18n-utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { localizeUrl } from './localize-url';
114 changes: 114 additions & 0 deletions packages/i18n-utils/src/locales.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* The locale sets here map roughly to those found in locales.php
*
* todo: move these into @automattic/languages as another downloaded resource
* todo: cleanup _shared.json - replace references to the below config options with imports from here
*/
export type Locale = string;
export const i18nDefaultLocaleSlug: Locale = 'en';
export const localesWithBlog: Locale[] = [ 'en', 'ja', 'es', 'pt', 'fr', 'pt-br' ];
export const localesWithPrivacyPolicy: Locale[] = [ 'en', 'fr', 'de' ];
export const localesWithCookiePolicy: Locale[] = [ 'en', 'fr', 'de' ];

type LocaleSubdomain = string;

export const localesToSubdomains: Record< string, LocaleSubdomain > = {
'pt-br': 'br',
br: 'bre',
zh: 'zh-cn',
'zh-hk': 'zh-tw',
'zh-sg': 'zh-cn',
kr: 'ko',
};

// replaces config( 'english_locales' )
export const englishLocales: Locale[] = [ 'en', 'en-gb' ];

// replaces config( 'livechat_support_locales' )
export const livechatSupportLocales: Locale[] = [ 'en', 'es', 'pt-br' ];

// replaces config( 'support_site_locales' )
export const supportSiteLocales: Locale[] = [
'ar',
'de',
'en',
'es',
'fr',
'he',
'id',
'it',
'ja',
'ko',
'nl',
'pt-br',
'ru',
'sv',
'tr',
'zh-cn',
'zh-tw',
];

// replaces config( 'forum_locales')
export const forumLocales: Locale[] = [
'ar',
'de',
'el',
'en',
'es',
'fa',
'fi',
'fr',
'id',
'it',
'ja',
'nl',
'pt',
'pt-br',
'ru',
'sv',
'th',
'tl',
'tr',
];

// replaces config( 'magnificent_non_en_locales')
export const magnificentNonEnLocales: Locale[] = [
'es',
'pt-br',
'de',
'fr',
'he',
'ja',
'it',
'nl',
'ru',
'tr',
'id',
'zh-cn',
'zh-tw',
'ko',
'ar',
'sv',
];

// replaces config( 'jetpack_com_locales')
export const jetpackComLocales: Locale[] = [
'en',
'ar',
'de',
'es',
'fr',
'he',
'id',
'it',
'ja',
'ko',
'nl',
'pt-br',
'ro',
'ru',
'sv',
'tr',
'zh-cn',
'zh-tw',
];
Loading

0 comments on commit 1446651

Please sign in to comment.