egg icon indicating copy to clipboard operation
egg copied to clipboard

egg-i18n 国际化问题求助

Open bhgx opened this issue 4 years ago • 4 comments

  • 最近开始使用vue,遇到问题了,求助。

  • 我是通过cookie来控制国际化,当用户通过en.xxx.com访问时,我在中间件中将cookie设置成en;当用户通过www.xxx.com访问时,我在中间件中将cookie设置成zh。每个请求都会执行中间件

  • 问题:当我访问www.xxx.com后,再访问en.xxx.com,浏览器加载出来的还是中文版

  • 问题追踪:当我访问www.xxx.com后,request的cookie的language值是zh,然后再访问en.xxx.com,服务器收到的请求中的language值还是zh,这时通过中间件来修改cookie值,然后执行后面的页面渲染逻辑,但渲染出来的还是中文页面

  • 我的疑惑:是不是因为egg的国际化处理逻辑在中间件之前就执行了?

language_handler.js(中间件)

module.exports = () => {
	return async function (ctx, next) {
		
		let host = ctx.ctx.request.header['host'], language = 'zh';

		if(host.startsWith('en')){
			language = 'en';
		}

		ctx.cookies.set('language', language ,{
			domain: '.xxx.com',
			httpOnly: false
		}); 
		await next();
	};
};

config.default.js

config.middleware = [ 'languageHandler']

config.i18n = {
    defaultLocale: 'zh',
    queryField: 'language',
    cookieField: 'language',
    cookieDomain: '.xxx.com',
    cookieMaxAge: '1y'
}

plugin.js

config.i18n = {
	enable: true,
	package: 'egg-i18n'
}

bhgx avatar Jun 09 '20 10:06 bhgx

修改 language_handler.js

module.exports = () => {
  return async function(ctx, next) {

    const host = ctx.request.header['host'];
    let language = 'zh-CN'; // 要确保和 config/locale中的国际化语言配置文件名匹配

    if (host.endsWith('/en')) {
      language = 'en-US'; // 要确保和 config/locale中的国际化语言配置文件名匹配
    }

    // 由于设置cookies后的对应字段不会更新到本次请求中(大约需要请求2次才会生效),所以使用 query 的优先级进行强制转换
    const url = ctx.request.url;
    ctx.request.url = `${url}${url.indexOf('?') < 0 ? '?' : '&'}language=${language}`;

    await ctx.cookies.set('language', language, {
      httpOnly: false
    });
    await next();
  };
};

相关配置 image

ChangedenCZD avatar Jun 10 '20 01:06 ChangedenCZD

是不是因为egg的国际化处理逻辑在中间件之前就执行了?

https://github.com/eggjs/egg-i18n/blob/master/app.js#L137

i18n 是在 coreMiddleware 的,在应用的 Middleware 之前

atian25 avatar Aug 31 '20 03:08 atian25

  • 最近开始使用vue,遇到问题了,求助。
  • 我是通过cookie来控制国际化,当用户通过en.xxx.com访问时,我在中间件中将cookie设置成en;当用户通过www.xxx.com访问时,我在中间件中将cookie设置成zh。每个请求都会执行中间件
  • 问题:当我访问www.xxx.com后,再访问en.xxx.com,浏览器加载出来的还是中文版
  • 问题追踪:当我访问www.xxx.com后,request的cookie的language值是zh,然后再访问en.xxx.com,服务器收到的请求中的language值还是zh,这时通过中间件来修改cookie值,然后执行后面的页面渲染逻辑,但渲染出来的还是中文页面
  • 我的疑惑:是不是因为egg的国际化处理逻辑在中间件之前就执行了?

language_handler.js(中间件)

module.exports = () => {
	return async function (ctx, next) {
		
		let host = ctx.ctx.request.header['host'], language = 'zh';

		if(host.startsWith('en')){
			language = 'en';
		}

		ctx.cookies.set('language', language ,{
			domain: '.xxx.com',
			httpOnly: false
		}); 
		await next();
	};
};

config.default.js

config.middleware = [ 'languageHandler']

config.i18n = {
    defaultLocale: 'zh',
    queryField: 'language',
    cookieField: 'language',
    cookieDomain: '.xxx.com',
    cookieMaxAge: '1y'
}

plugin.js

config.i18n = {
	enable: true,
	package: 'egg-i18n'
}

最终是如何解决的呢

keepFur avatar Jun 02 '21 10:06 keepFur

修改 language_handler.js

module.exports = () => {
  return async function(ctx, next) {

    const host = ctx.request.header['host'];
    let language = 'zh-CN'; // 要确保和 config/locale中的国际化语言配置文件名匹配

    if (host.endsWith('/en')) {
      language = 'en-US'; // 要确保和 config/locale中的国际化语言配置文件名匹配
    }

    // 由于设置cookies后的对应字段不会更新到本次请求中(大约需要请求2次才会生效),所以使用 query 的优先级进行强制转换
    const url = ctx.request.url;
    ctx.request.url = `${url}${url.indexOf('?') < 0 ? '?' : '&'}language=${language}`;

    await ctx.cookies.set('language', language, {
      httpOnly: false
    });
    await next();
  };
};

相关配置 image

找个方法可行,谢谢大佬

skyrcHCP avatar Oct 09 '21 01:10 skyrcHCP