nuxt-i18nのstrategyオプション
strategyオプションとは
strategyオプションはURLに言語コードを含めるかどうかを設定するオプションです。
strategyオプションには次の値を指定できます。
no_prefix:URLに言語コードを含めません
prefix_except_default:デフォルトの言語以外でURLに言語コードを含めます
prefix:URLに言語コードを含めます
prefix_and_default:(デフォルト)すべての言語でURLに言語コードを含めますが、言語コードを省略してもデフォルト言語として解釈します。
table:strategyオプションの概要
値 / /ja /en
no_prefix ◯ ✕ ✕
prefix_expect_default ◯ ✕ ◯
prefix ✕ ◯ ◯
prefix_and_default ◯ ◯ ◯
(デフォルト言語=ja)
言語コードのフォールバック
仕様上あり得る挙動が /にアクセスしたら自動的に/jaへリダイレクトするというもの。
この挙動にnuxt-i18nモジュール自体は対応していませんので、自力で実装する必要があります。
onuma.icon 田村くんが持っている案件ではそれをして欲しいと言われたのでしょうか?そこまで強いこだわりがないならprefix_and_defaultを設定してどちらでも見れるようにしたらそこまで問題ないような気がしたのですが・・・🤔
プラグインで実装する by tamuraryoya.icon
URLの正規化を行うプラグイン、i18n-path-normalizerみたいなプラグインを作りました。
実際の実装よりコメント多め。
★注意:
クエリも明示的に渡さないといけない
デフォルトの言語コードとかでタイポすると、無限リダイレクトが発生する
★不明点:
この仕組を利用して、各nuxt-linkには言語コードなしのURLを指定しているが、SEO的にいかがなものだろうか?(hrefの向き先が実際は存在しないURL)
:to="localePath('/foo/bar')"とlocalePathメソッド通せばいいのだが、今更修正するのが億劫
code:src/plugins/i18n-path-normalizer.ts
/**
* @file i18nのパスの正規化を行うプラグイン
*/
import { Plugin } from '@nuxt/types';
import { NuxtVueI18n } from 'nuxt-i18n';
import path from 'path';
/**
* 言語コードのパスパラメータつきのパスに正規化する関数
* @param originalPath オリジナルのパス
* @param locale 選択中の言語
* @param locales 言語一覧
* @returns 言語コードを含むパス もしくは null (言語コードを含むパスが渡された場合)
*/
const normalizeI18nPath = (
originalPath: string,
locale: NuxtVueI18n.Locale,
locales: Array<NuxtVueI18n.Locale | NuxtVueI18n.Options.LocaleObject>
): string | null => {
// パスの最初のディレクトリを取得する
const matches = originalPath.match(/^\/(^/*)\/?/); if (!matches) {
return null;
}
// パスの中からマッチしたディレクトリ名
const localeCode = matches1; // localeCodeが対応する言語コードか
const isLocaleValid = locales.some((locale) => {
const code = typeof locale === 'string' ? locale : locale.code;
return code === localeCode;
});
// 言語コードがパスに含まれる場合は何も返さない
if (isLocaleValid) {
return null;
}
// 言語コードを含むURLを返す
return path.join('/', locale, originalPath);
};
/**
* Nuxt Plugin
*/
const plugin: Plugin = ({ app, query, req, redirect }): void => {
const { router, i18n } = app;
// SSR時の処理
if (process.server) {
const { originalUrl = '' } = req;
const { locale, locales = [] } = i18n;
// パスの正規化
const normalizedPath = normalizeI18nPath(originalUrl, locale, locales);
if (normalizedPath) {
redirect(normalizedPath, query);
}
return;
}
if (!router) {
return;
}
// CSR時の処理
router.beforeEach((to, from, next) => {
const { locale, locales = [] } = i18n;
// パスの正規化
const normalizedPath = normalizeI18nPath(to.path, locale, locales);
if (!normalizedPath) {
next();
return;
}
next({
path: normalizedPath,
query: to.query,
});
});
};
export default plugin;
onuma.icon 便利なライブラリですね😄自前で実装しようとしていたのが馬鹿らしくなる・・・
👍 onuma onuma.icon がいいねしました on 2020/4/13