mirror of https://github.com/alibaba/ice.git
fix: some i18n bugs (#5400)
* fix: i18n plugin not work in IE11 * feat: add setting for block cookie setting i18n locale (#5437) * feat: add setting for block cookie setting i18n locale * add I18nAppConfig to IAppConfig & change appConfig key to i18n Co-authored-by: liyidong <liyidong@baidu.com> Co-authored-by: leo.lyd <leo.lyd@alibaba-inc.com> * fix locale will always in default when execute history.push in cookie blocked mode (#5441) * feat: add setting for block cookie setting i18n locale * add I18nAppConfig to IAppConfig & change appConfig key to i18n * fix: fix locale will always in default when execute history.push in cookie blocked mode Co-authored-by: liyidong <liyidong@baidu.com> Co-authored-by: leo.lyd <leo.lyd@alibaba-inc.com> * fix: modifyHistory params delivery error (#5442) * feat: add setting for block cookie setting i18n locale * add I18nAppConfig to IAppConfig & change appConfig key to i18n * fix: fix locale will always in default when execute history.push in cookie blocked mode * fix: fix modifyHistory params delivery error Co-authored-by: liyidong <liyidong@baidu.com> Co-authored-by: leo.lyd <leo.lyd@alibaba-inc.com> * feat: no defaultLocale return from getDetectedLocaleFromPathname & adjust detect locale sequence in getDetectedLocale function (#5458) * feat: add setting for block cookie setting i18n locale * add I18nAppConfig to IAppConfig & change appConfig key to i18n * fix: fix locale will always in default when execute history.push in cookie blocked mode * fix: fix modifyHistory params delivery error * feat: no defaultLocale return from getDetectedLocaleFromPathname & adjust detect locale sequence in getDetectedLocale function Co-authored-by: liyidong <liyidong@baidu.com> Co-authored-by: leo.lyd <leo.lyd@alibaba-inc.com> * fix: redirect incorrect i18n page (#5461) * fix: redirect incorrect i18n page * fix: eslint warning * fix: cookie path Co-authored-by: srhb18 <srhb18@163.com> Co-authored-by: liyidong <liyidong@baidu.com> Co-authored-by: leo.lyd <leo.lyd@alibaba-inc.com>
This commit is contained in:
parent
201393172e
commit
1ee7db0419
|
|
@ -5,7 +5,8 @@
|
|||
{
|
||||
"locales": [
|
||||
"zh-CN",
|
||||
"en-US"
|
||||
"en-US",
|
||||
"zh-HK"
|
||||
],
|
||||
"defaultLocale": "zh-CN",
|
||||
"autoRedirect": true
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export const LOCALES = {
|
||||
ENGLISH: 'en-US',
|
||||
ZH_CN: 'zh-CN'
|
||||
ZH_CN: 'zh-CN',
|
||||
zh_HK: 'zh-HK',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,18 @@ export const messages = {
|
|||
basicLayout: '主布局',
|
||||
userLayout: '用户布局',
|
||||
notFound: '未找到页面',
|
||||
userLogin: '用户登录页'
|
||||
userLogin: '用户登录页',
|
||||
},
|
||||
[LOCALES.zh_HK]: {
|
||||
homeTitle: '首頁',
|
||||
aboutTitle: '關於',
|
||||
currentLocale: '當前語言',
|
||||
defaultLocale: '默認語言',
|
||||
configuredLocales: '配置的語言',
|
||||
localeSwitcher: '語言切換',
|
||||
basicLayout: '主佈局',
|
||||
userLayout: '用戶佈局',
|
||||
notFound: '未找到頁面',
|
||||
userLogin: '用戶登錄頁',
|
||||
},
|
||||
};
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "build-plugin-ice-i18n",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.2",
|
||||
"description": "ICE i18n build-scripts plugin",
|
||||
"author": "ice-admin@alibaba-inc.com",
|
||||
"homepage": "https://github.com/alibaba/ice#readme",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { I18nConfig } from './types';
|
|||
import { LOCALE_COOKIE_KEY } from './constants';
|
||||
|
||||
export default async function (
|
||||
{ onGetWebpackConfig, getValue, applyMethod }: IPluginAPI,
|
||||
{ onGetWebpackConfig, getValue, applyMethod }: IPluginAPI,
|
||||
i18nConfig: I18nConfig,
|
||||
) {
|
||||
checkI18nConfig(i18nConfig);
|
||||
|
|
@ -20,8 +20,8 @@ export default async function (
|
|||
|
||||
// copy templates to .ice/i18n dir
|
||||
applyMethod(
|
||||
'addPluginTemplate',
|
||||
path.join(__dirname, 'templates'),
|
||||
'addPluginTemplate',
|
||||
path.join(__dirname, 'templates'),
|
||||
{ LOCALE_COOKIE_KEY, i18nConfig, i18nRouting }
|
||||
);
|
||||
applyMethod(
|
||||
|
|
@ -39,12 +39,23 @@ export default async function (
|
|||
// export API
|
||||
// import { useLocale, getAllLocales, getDefaultLocale, getLocale } from 'ice';
|
||||
applyMethod(
|
||||
'addExport',
|
||||
{
|
||||
source: './plugins/i18n',
|
||||
'addExport',
|
||||
{
|
||||
source: './plugins/i18n',
|
||||
importSource: '$$ice/plugins/i18n',
|
||||
exportMembers: ['useLocale', 'getAllLocales', 'getDefaultLocale', 'getLocale', 'setLocale']
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// set I18nAppConfig to IAppConfig
|
||||
applyMethod(
|
||||
'addAppConfigTypes',
|
||||
{
|
||||
source: '../plugins/i18n/pluginRuntime/types',
|
||||
specifier: '{ I18nAppConfig }',
|
||||
exportName: 'i18n?: I18nAppConfig'
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function checkI18nConfig(i18nConfig: I18nConfig) {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import * as React from 'react';
|
||||
import { History } from 'history';
|
||||
import Cookies from 'universal-cookie';
|
||||
import { I18nProvider, getLocaleFromCookies } from '$ice/i18n';
|
||||
import { I18nProvider, getLocaleFromCookies, getLocale } from '$ice/i18n';
|
||||
import { LOCALE_COOKIE_KEY } from './constants';
|
||||
import getLocaleData from './utils/getLocaleData';
|
||||
import { I18nConfig } from './types';
|
||||
import { I18nConfig, I18nAppConfig } from './types';
|
||||
import normalizeLocalePath from './utils/normalizeLocalePath';
|
||||
import addRoutesByLocales from './utils/addRoutesByLocales';
|
||||
import getRedirectIndexRoute from './utils/getRedirectIndexRoute';
|
||||
|
|
@ -12,12 +12,13 @@ import getRedirectIndexRoute from './utils/getRedirectIndexRoute';
|
|||
export default ({ modifyRoutes, buildConfig, addProvider, appConfig }) => {
|
||||
const { i18n: i18nConfig } = buildConfig;
|
||||
const { i18nRouting, autoRedirect } = i18nConfig;
|
||||
const { router: appConfigRouter = {} } = appConfig;
|
||||
const { router: appConfigRouter = {}, i18n: i18nAppConfig = {} } = appConfig;
|
||||
const { blockCookie = false } = i18nAppConfig;
|
||||
const { history = {}, basename } = appConfigRouter;
|
||||
|
||||
if (i18nRouting !== false) {
|
||||
modifyRoutes((routes) => {
|
||||
// routes 值是被 formatRoutes 方法处理后返回的结果
|
||||
// routes 值是被 formatRoutes 方法处理后返回的结果
|
||||
const modifiedRoutes = addRoutesByLocales(routes, i18nConfig);
|
||||
|
||||
if (autoRedirect === true) {
|
||||
|
|
@ -38,11 +39,12 @@ export default ({ modifyRoutes, buildConfig, addProvider, appConfig }) => {
|
|||
|
||||
if (!process.env.__IS_SERVER__) {
|
||||
const { detectedLocale } = getLocaleData({ url: window.location, i18nConfig, basename });
|
||||
setInitICELocaleToCookie(detectedLocale);
|
||||
const cookieBlocked = typeof blockCookie === 'function' ? blockCookie() : blockCookie;
|
||||
setInitICELocaleToCookie(detectedLocale, cookieBlocked);
|
||||
}
|
||||
|
||||
if (i18nRouting !== false) {
|
||||
modifyHistory(history, i18nConfig, basename);
|
||||
modifyHistory(history, i18nConfig, i18nAppConfig, basename);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -56,20 +58,21 @@ function Provider() {
|
|||
};
|
||||
}
|
||||
|
||||
function setInitICELocaleToCookie(locale: string) {
|
||||
function setInitICELocaleToCookie(locale: string, cookieBlocked: boolean) {
|
||||
const cookies = new Cookies();
|
||||
const iceLocale = cookies.get(LOCALE_COOKIE_KEY);
|
||||
if (!iceLocale) {
|
||||
cookies.set(LOCALE_COOKIE_KEY, locale);
|
||||
if (!cookieBlocked) {
|
||||
cookies.set(LOCALE_COOKIE_KEY, locale, { path: '/' });
|
||||
}
|
||||
}
|
||||
|
||||
function modifyHistory(history: History, i18nConfig: I18nConfig, basename?: string) {
|
||||
function modifyHistory(history: History, i18nConfig: I18nConfig, i18nAppConfig: I18nAppConfig, basename?: string) {
|
||||
const originHistory = { ...history };
|
||||
const { defaultLocale } = i18nConfig;
|
||||
const { blockCookie = false } = i18nAppConfig;
|
||||
const cookieBlocked = typeof blockCookie === 'function' ? blockCookie() : blockCookie;
|
||||
|
||||
function getLocalePath(
|
||||
originPathname: string,
|
||||
originPathname: string,
|
||||
locale: string,
|
||||
) {
|
||||
const localePathResult = normalizeLocalePath(originPathname, i18nConfig, basename);
|
||||
|
|
@ -87,15 +90,15 @@ function modifyHistory(history: History, i18nConfig: I18nConfig, basename?: stri
|
|||
return path;
|
||||
}
|
||||
|
||||
history.push = function(path: string | Location, state?: unknown) {
|
||||
const locale = getLocaleFromCookies() || defaultLocale;
|
||||
history.push = function(path: string | Location, state?: unknown, localeParam?: string) {
|
||||
const locale = localeParam || (cookieBlocked ? getLocale() : getLocaleFromCookies()) || defaultLocale;
|
||||
const pathname = getPathname(path);
|
||||
const localePath = getLocalePath(pathname, locale);
|
||||
originHistory.push(localePath, state);
|
||||
};
|
||||
|
||||
history.replace = function(path: string | Location, state?: unknown) {
|
||||
const locale = getLocaleFromCookies() || defaultLocale;
|
||||
history.replace = function(path: string | Location, state?: unknown, localeParam?: string) {
|
||||
const locale = localeParam || (cookieBlocked ? getLocale() : getLocaleFromCookies()) || defaultLocale;
|
||||
const pathname = getPathname(path);
|
||||
const localePath = getLocalePath(pathname, locale);
|
||||
originHistory.replace(localePath, state);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export function getAllLocales(): string[] {
|
|||
}
|
||||
|
||||
<% if (i18nRouting !== false) {%>
|
||||
function getDetectedLocaleFromPath(locales: string[], defaultLocale: string) {
|
||||
function getDetectedLocaleFromPath(locales: string[]) {
|
||||
const appConfig = getAppConfig();
|
||||
if (history === null) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
|
|
@ -65,7 +65,7 @@ function getDetectedLocaleFromPath(locales: string[], defaultLocale: string) {
|
|||
}
|
||||
const { location: { pathname } } = history;
|
||||
|
||||
return getDetectedLocaleFromPathname({ pathname, locales, defaultLocale, basename: appConfig?.router?.basename });
|
||||
return getDetectedLocaleFromPathname({ pathname, locales, basename: appConfig?.router?.basename });
|
||||
}
|
||||
<% } %>
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ function getDetectedLocaleFromPath(locales: string[], defaultLocale: string) {
|
|||
export function getLocale(): string {
|
||||
return (
|
||||
<% if (i18nRouting !== false) {%>
|
||||
getDetectedLocaleFromPath(locales, defaultLocale) ||
|
||||
getDetectedLocaleFromPath(locales) ||
|
||||
<% } %>
|
||||
cookies.get(LOCALE_COOKIE_KEY) ||
|
||||
defaultLocale
|
||||
|
|
@ -90,7 +90,16 @@ export function setLocale(locale: string) {
|
|||
}
|
||||
|
||||
function setLocaleToCookies(locale: string) {
|
||||
cookies.set(LOCALE_COOKIE_KEY, locale, { path: '/' });
|
||||
<% if (i18nRouting !== false) {%>
|
||||
const { i18n: i18nConfig = {} } = getAppConfig();
|
||||
const { blockCookie = false } = i18nConfig;
|
||||
const cookieBlocked = typeof blockCookie === 'function' ? blockCookie() : blockCookie;
|
||||
if (!cookieBlocked) {
|
||||
<% } %>
|
||||
cookies.set(LOCALE_COOKIE_KEY, locale, { path: '/' });
|
||||
<% if (i18nRouting !== false) {%>
|
||||
}
|
||||
<% } %>
|
||||
}
|
||||
|
||||
export function getLocaleFromCookies() {
|
||||
|
|
|
|||
|
|
@ -7,4 +7,8 @@ export interface I18nConfig {
|
|||
autoRedirect?: true;
|
||||
// 国际化路由
|
||||
i18nRouting?: false;
|
||||
}
|
||||
}
|
||||
|
||||
export interface I18nAppConfig {
|
||||
blockCookie?: boolean | Function;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,21 @@
|
|||
import replaceBasename from './replaceBasename';
|
||||
|
||||
interface GetDetectedLocalFromPathnameParams {
|
||||
pathname: string;
|
||||
locales: string[];
|
||||
basename?: string;
|
||||
}
|
||||
/**
|
||||
* 开启国际化路由时,通过 pathname 获取当前语言
|
||||
*/
|
||||
function getDetectedLocaleFromPathname(
|
||||
{
|
||||
pathname,
|
||||
locales,
|
||||
defaultLocale,
|
||||
basename,
|
||||
}: {
|
||||
pathname: string;
|
||||
locales: string[];
|
||||
defaultLocale: string;
|
||||
basename?: string;
|
||||
}) {
|
||||
function getDetectedLocaleFromPathname({ pathname, locales, basename }: GetDetectedLocalFromPathnameParams) {
|
||||
const normalizedPathname = replaceBasename(pathname, basename);
|
||||
const pathnameParts = normalizedPathname.split('/').filter(pathnamePart => pathnamePart);
|
||||
|
||||
let detectedLocale = defaultLocale;
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const locale of locales) {
|
||||
// 从路径获取locale时,默认路径不再命中默认语言,返回空字符串,调用业务需执行兜底默认语言
|
||||
let detectedLocale = '';
|
||||
for (let index = 0; index < locales.length; index++) {
|
||||
const locale = locales[index];
|
||||
if (pathnameParts[0] === locale) {
|
||||
detectedLocale = locale;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ export default function getLocaleData({
|
|||
}
|
||||
|
||||
function getDetectedLocale(
|
||||
{
|
||||
pathname,
|
||||
{
|
||||
pathname,
|
||||
i18nConfig,
|
||||
headers = {},
|
||||
basename,
|
||||
}: {
|
||||
pathname: string,
|
||||
}: {
|
||||
pathname: string,
|
||||
i18nConfig: I18nConfig,
|
||||
headers?: Record<string, string>,
|
||||
basename?: string,
|
||||
|
|
@ -49,14 +49,15 @@ function getDetectedLocale(
|
|||
} else {
|
||||
cookies = (new Cookies()).getAll();
|
||||
}
|
||||
|
||||
|
||||
const { defaultLocale, locales, i18nRouting } = i18nConfig;
|
||||
|
||||
const detectedLocale =
|
||||
getLocaleFromCookie(locales, cookies) ||
|
||||
getPreferredLocale(locales, headers) ||
|
||||
(i18nRouting === false ? undefined : getDetectedLocaleFromPathname({ pathname, locales, basename, defaultLocale })) ||
|
||||
defaultLocale;
|
||||
// 检测获取Locale的优先级为:path前缀 > cookie > 浏览器语言设置 > 默认语言
|
||||
const detectedLocale =
|
||||
(i18nRouting === false ? undefined : getDetectedLocaleFromPathname({ pathname, locales, basename })) ||
|
||||
getLocaleFromCookie(locales, cookies) ||
|
||||
getPreferredLocale(locales, headers) ||
|
||||
defaultLocale;
|
||||
|
||||
return detectedLocale;
|
||||
}
|
||||
|
|
@ -66,7 +67,7 @@ function getDetectedLocale(
|
|||
* 仅在 pathname 为 `/` 或者 `/${basename}` 时重定向
|
||||
*/
|
||||
function getRedirectUrl(
|
||||
pathname: string,
|
||||
pathname: string,
|
||||
i18nConfig: I18nConfig & { detectedLocale: string },
|
||||
basename?: string,
|
||||
) {
|
||||
|
|
@ -74,9 +75,9 @@ function getRedirectUrl(
|
|||
const normalizedPathname = replaceBasename(pathname, basename);
|
||||
const isRootPath = normalizedPathname === '/';
|
||||
if (
|
||||
autoRedirect === true &&
|
||||
i18nRouting !== false &&
|
||||
isRootPath &&
|
||||
autoRedirect === true &&
|
||||
i18nRouting !== false &&
|
||||
isRootPath &&
|
||||
defaultLocale !== detectedLocale
|
||||
) {
|
||||
return `/${detectedLocale}`;
|
||||
|
|
@ -94,7 +95,7 @@ function getPreferredLocale(locales: string[], headers?: { [key: string]: string
|
|||
const acceptLanguageValue = headers?.['accept-language'];
|
||||
return acceptLanguagePick(locales, acceptLanguageValue);
|
||||
} else {
|
||||
const acceptLanguages = window.navigator.languages;
|
||||
const acceptLanguages = window.navigator.languages || [];
|
||||
return acceptLanguages.find(acceptLanguage => locales.includes(acceptLanguage));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@ import getLocaleData from './getLocaleData';
|
|||
*/
|
||||
export default function getRedirectIndexRoute(originRoutes: any[], i18nConfig: I18nConfig, basename?: string) {
|
||||
function walkRoute(routes: any[]) {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const route of routes) {
|
||||
for (let index = 0; index < routes.length; index++) {
|
||||
const route = routes[index];
|
||||
const { path, children, ...rest } = route;
|
||||
if (path === '/') {
|
||||
if (children) {
|
||||
|
|
@ -27,10 +27,10 @@ export default function getRedirectIndexRoute(originRoutes: any[], i18nConfig: I
|
|||
...route,
|
||||
exact: true,
|
||||
component: (props: any) => (
|
||||
<IndexComponent
|
||||
{...props}
|
||||
i18nConfig={i18nConfig}
|
||||
basename={basename}
|
||||
<IndexComponent
|
||||
{...props}
|
||||
i18nConfig={i18nConfig}
|
||||
basename={basename}
|
||||
OriginIndexComponent={route.component}
|
||||
/>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,10 +9,10 @@ function normalizeLocalePath(
|
|||
pathname = replaceBasename(pathname, basename);
|
||||
const { defaultLocale, locales } = i18nConfig;
|
||||
const subPaths = pathname.split('/');
|
||||
let detectedLocale = defaultLocale;
|
||||
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
for (const locale of locales) {
|
||||
let detectedLocale = defaultLocale;
|
||||
for (let index = 0; index < locales.length; index++) {
|
||||
const locale = locales[index];
|
||||
if (subPaths[1] && subPaths[1] === locale) {
|
||||
detectedLocale = locale;
|
||||
subPaths.splice(1, 1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue