Edge 151のLanguageDetector変更|繁体字・簡体字をzh-Hant/zh-Hansで判定

Microsoft Edge 151では、LanguageDetector APIが繁体字中国語と簡体字中国語を区別できるようになりました。これまで両方ともzhとして返されていた判定結果が、繁体字はzh-Hant、簡体字はzh-Hansとして返されます。

この変更で注意したいのは、detectedLanguage === "zh"のような完全一致で中国語を判定しているコードです。Edge 151では条件に一致しなくなり、中国語向けの翻訳や画面表示が実行されない可能性があります。

Microsoftが2026年7月30日(UTC)に公開・更新した情報では、本変更は情報提供として案内されています。ただし、LanguageDetector APIの戻り値を利用しているWebサイトやブラウザー拡張機能では、コード、テスト、データ保存形式を確認しておく必要があります。(Microsoft Learn)

日程Fit。無料・登録不要。「いつ空いてる?」を、ひとつのリンクで。リンクを送って、○△×でかんたん日程調整。無料で日程を作る。
目次

Edge 151のLanguageDetectorがzh-Hantとzh-Hansを返す変更

Microsoft Edge 151では、LanguageDetector APIによる中国語の判定結果が次のように変わります。

入力された文章従来の判定結果Edge 151の判定結果
繁体字中国語zhzh-Hant
簡体字中国語zhzh-Hans

zhは中国語を表す言語コードです。一方、HantHansは文字体系を表すサブタグです。

  • zh-Hant:繁体字で書かれた中国語
  • zh-Hans:簡体字で書かれた中国語
  • zh:文字体系を指定しない中国語

LanguageDetector APIのdetect()が返すdetectedLanguageには、BCP 47形式の言語タグが格納されます。Edge 151では、この言語タグを使って中国語の文字体系まで区別できるようになった形です。(Microsoft Learn)

既存コードに影響する理由

変更されるのはAPIの呼び出し方法ではなく、主に戻り値の内容です。そのため、API自体は動いていても、判定結果を処理する後続コードだけが正しく動かなくなることがあります。

zhとの完全一致は成立しなくなる

影響を受けやすいのが、次のような実装です。

const results = await detector.detect(text);
const bestResult = results[0];

if (bestResult.detectedLanguage === "zh") {
  showChineseContent();
}

繁体字の判定結果がzh-Hant、簡体字の判定結果がzh-Hansになると、どちらも"zh"とは一致しません。

その結果、次のような不具合が起こる可能性があります。

  • 中国語向けの翻訳処理が始まらない
  • 中国語用フォントやCSSが適用されない
  • 問い合わせを中国語担当者へ振り分けられない
  • 中国語用の入力チェックが実行されない
  • 分析画面で中国語の件数がゼロになる

JavaScriptの例外が発生するとは限らないため、エラーログだけでは発見しにくい点にも注意が必要です。

2文字の言語コードを前提とした処理も確認する

zh-Hantzh-Hansはいずれもzhより長い文字列です。次のような実装がないか確認してください。

const language = detectedLanguage.slice(0, 2);
const supportedLanguages = ["ja", "en", "zh"];

if (!supportedLanguages.includes(detectedLanguage)) {
  useDefaultLanguage();
}
const messages = {
  ja: japaneseMessages,
  en: englishMessages,
  zh: chineseMessages
};

const selectedMessages = messages[detectedLanguage];

特に、許可リスト、オブジェクトのキー、正規表現、TypeScriptの型定義は影響を受けやすい箇所です。

データベースや分析基盤にも影響する

検出した言語タグをサーバーへ送信している場合は、フロントエンドだけでなくバックエンドも確認します。

代表的な確認箇所は次のとおりです。

確認箇所起こり得る問題
データベースの文字数制限2文字固定の列に保存できない
バリデーション^[a-z]{2}$などの条件で拒否される
集計処理zhzh-Hantzh-Hansが別々に集計される
外部API連携2文字コードしか受け付けないAPIでエラーになる
TypeScriptの型"ja" | "en" | "zh"に代入できない
テストのスナップショット期待値がzhのままで失敗する

データベースの列がCHAR(2)になっている場合は、BCP 47形式の言語タグを保存できる長さへ変更する必要があります。

中国語を区別するかどうかで対応方法を決める

Edge 151への対応方法は、アプリが繁体字と簡体字を区別する必要があるかどうかで変わります。

繁体字と簡体字を区別したい場合

翻訳先、表示文言、検索辞書、コンテンツの振り分けなどを文字体系ごとに変えたい場合は、zh-Hantzh-Hansをそのまま利用します。

function getChineseScript(languageTag) {
  const locale = new Intl.Locale(languageTag);

  if (locale.language !== "zh") {
    return "not-chinese";
  }

  if (locale.script === "Hant") {
    return "traditional";
  }

  if (locale.script === "Hans") {
    return "simplified";
  }

  return "unspecified";
}

利用例は次のとおりです。

const script = getChineseScript(result.detectedLanguage);

switch (script) {
  case "traditional":
    showTraditionalChineseContent();
    break;

  case "simplified":
    showSimplifiedChineseContent();
    break;

  case "unspecified":
    showGenericChineseContent();
    break;

  default:
    showDefaultContent();
}

文字列を直接分割する方法もありますが、BCP 47形式の言語タグを扱う場合はIntl.Localeを利用すると、言語部分と文字体系部分を明確に分けられます。

中国語かどうかだけ分かればよい場合

繁体字と簡体字を同じ処理へ流す場合は、完全一致ではなく基本言語を確認します。

変更前のコードです。

const isChinese = detectedLanguage === "zh";

変更後は次のようにします。

function isChineseLanguage(languageTag) {
  try {
    const locale = new Intl.Locale(languageTag);
    return locale.language === "zh";
  } catch {
    return false;
  }
}

これなら、次のタグをいずれも中国語として扱えます。

isChineseLanguage("zh");      // true
isChineseLanguage("zh-Hant"); // true
isChineseLanguage("zh-Hans"); // true

単純にlanguageTag.startsWith("zh")と判定する方法もありますが、言語タグとして解析する意図が明確なIntl.Localeの利用が分かりやすいでしょう。

外部システムがzhしか受け付けない場合

連携先のAPIや既存システムがzh-Hantzh-Hansに対応していない場合は、連携直前にzhへ変換します。

function toLegacyLanguageCode(languageTag) {
  try {
    const locale = new Intl.Locale(languageTag);

    if (locale.language === "zh") {
      return "zh";
    }

    return locale.language;
  } catch {
    return "und";
  }
}

重要なのは、LanguageDetector APIから受け取った直後にすべてzhへ戻さないことです。

アプリ内部ではzh-Hantzh-Hansを保持し、互換性のために必要な連携部分だけをzhへ変換すると、将来的に繁体字と簡体字を使い分けたくなったときにも対応しやすくなります。

Edge 151に対応したLanguageDetectorの実装例

LanguageDetector APIを利用するときは、戻り値の変更だけでなく、APIの利用可否、モデルの準備状態、判定不能、セッションの破棄も考慮します。

async function detectLanguage(text) {
  const normalizedText = text.trim();

  if (!normalizedText) {
    return {
      status: "empty",
      detectedLanguage: "und",
      confidence: 0
    };
  }

  if (!("LanguageDetector" in globalThis)) {
    return {
      status: "unsupported",
      detectedLanguage: "und",
      confidence: 0
    };
  }

  const availability = await LanguageDetector.availability();

  if (availability === "unavailable") {
    return {
      status: "unavailable",
      detectedLanguage: "und",
      confidence: 0
    };
  }

  const detector = await LanguageDetector.create({
    expectedInputLanguages: [
      "ja",
      "en",
      "zh-Hant",
      "zh-Hans"
    ]
  });

  try {
    const results = await detector.detect(normalizedText);
    const bestResult = results[0];

    if (!bestResult || bestResult.detectedLanguage === "und") {
      return {
        status: "undetermined",
        detectedLanguage: "und",
        confidence: bestResult?.confidence ?? 0
      };
    }

    const locale = new Intl.Locale(bestResult.detectedLanguage);

    return {
      status: "detected",
      detectedLanguage: bestResult.detectedLanguage,
      baseLanguage: locale.language,
      script: locale.script || null,
      confidence: bestResult.confidence
    };
  } finally {
    detector.destroy();
  }
}

呼び出し側では、用途に応じて基本言語と文字体系を使い分けます。

const result = await detectLanguage(userInput);

if (result.status !== "detected") {
  showLanguageSelection();
} else if (
  result.baseLanguage === "zh" &&
  result.script === "Hant"
) {
  showTraditionalChineseContent();
} else if (
  result.baseLanguage === "zh" &&
  result.script === "Hans"
) {
  showSimplifiedChineseContent();
} else {
  showContentForLanguage(result.baseLanguage);
}

LanguageDetector APIは端末上のモデルを使って言語を検出します。初回利用時にはモデルのダウンロードが必要になる場合があり、availability()ではunavailabledownloadabledownloadingavailableなどの状態を確認できます。

また、detect()の結果は信頼度が高い順に並び、各結果にはdetectedLanguageconfidenceが含まれます。利用後はdestroy()でセッションを破棄できます。(Microsoft Learn)

zh-Hantzh-Hansを地域コードとして扱わない

HantHansは文字体系を表すタグであり、国や地域を直接示すものではありません。

そのため、次のような決め打ちは避けた方が安全です。

if (detectedLanguage === "zh-Hant") {
  userCountry = "TW";
}

繁体字の文章を検出できても、利用者の居住地や希望する地域設定まで確定できるわけではありません。

地域ごとに日付形式、通貨、住所、固有表現などを切り替える場合は、言語検出結果とは別に次の情報を使います。

  • ユーザーが選択した表示地域
  • アカウントに保存されたロケール
  • ブラウザーの言語設定
  • サービス側で設定した地域情報

LanguageDetectorの結果は、あくまで「入力された文章がどの言語・文字体系で書かれている可能性が高いか」を判断する材料として利用します。

短い文章だけで判定しない

Microsoftは、短いテキストや単語だけを入力した場合、言語検出結果が不正確または不安定になる可能性があると説明しています。(Microsoft Learn)

例えば、次のような入力は判定材料が少なくなります。

你好
商品

漢字だけの短い文字列では、中国語、日本語、その他の言語を区別しにくい場合があります。繁体字と簡体字のテストも、1文字や単語ではなく、ある程度の長さがある自然な文章で実施してください。

実際のサービスでは、次のような対策が有効です。

  • 一定文字数未満では自動判定しない
  • 信頼度が低い場合はユーザーに選択してもらう
  • 判定結果だけで重要な処理を確定しない
  • 入力が増えた時点で再判定する
  • 手動で選択した言語を優先する

信頼度の基準値は、サービスの入力内容や誤判定時の影響によって変わります。根拠なく固定値を採用せず、実際の文章データを使って調整することが重要です。

Edge 151への更新前後で実施したいテスト

繁体字と簡体字の文章を1件ずつ確認するだけでは不十分です。既存の言語判定処理全体を対象にテストします。

テスト内容確認するポイント
十分な長さの繁体字文章最上位候補がzh-Hantになるか
十分な長さの簡体字文章最上位候補がzh-Hansになるか
日本語の漢字を含む文章中国語向け処理へ誤って進まないか
繁体字と簡体字が混在した文章想定外の結果でも画面が壊れないか
数字や記号が中心の文章undや低信頼度を処理できるか
1語だけの短い入力自動確定せずフォールバックできるか
APIを利用できないブラウザー手動選択などの代替手段が表示されるか
初回モデルダウンロード時読み込み中の状態を利用者へ示せるか
既存のzhデータ過去データを引き続き処理できるか
外部APIへの送信zh-Hantzh-Hansが拒否されないか

古い環境からzhが渡される可能性も考え、移行期間中はzhzh-Hantzh-Hansの3種類を受け入れる実装にしておくと安全です。

コード以外で見落としやすい確認箇所

LanguageDetectorの呼び出し部分を直しても、次の設定や資料に古い前提が残っていることがあります。

  • API仕様書の言語コード一覧
  • OpenAPIやJSON Schemaの列挙値
  • TypeScriptの型定義
  • 単体テストの期待値
  • E2Eテストの判定条件
  • モックデータ
  • ダッシュボードの集計条件
  • ログ検索用のクエリ
  • データベースの制約
  • CSV出力の仕様
  • 翻訳サービスへの変換表
  • 運用担当者向けの手順書

特に、分析データをWHERE language = 'zh'で集計している場合は、Edge 151以降のデータが集計から漏れる可能性があります。

文字体系を分けずに中国語全体を集計するなら、zhzh-Hantzh-Hansを同じグループへまとめます。一方、繁体字と簡体字の利用状況を分析したい場合は、元の言語タグを保持したまま別々に集計します。

Edge 151対応で実施すること

まず、ソースコードと設定ファイルから次の文字列を検索します。

=== "zh"
== "zh"
language: "zh"
["ja", "en", "zh"]
CHAR(2)
VARCHAR(2)
^[a-z]{2}$

そのうえで、用途に応じて対応を分けます。

  1. 中国語かどうかだけ判定する処理は、基本言語がzhか確認する
  2. 繁体字と簡体字を分ける処理は、HantHansを確認する
  3. 外部システムが新しいタグに非対応なら、連携境界でzhへ変換する
  4. データベースや型定義の文字数・列挙値を見直す
  5. 短文、混在文、判定不能、モデル未準備のケースをテストする
  6. 過去のzhと新しいzh-Hantzh-Hansを同時に処理できるようにする

Edge 151のLanguageDetector変更に対応するうえで重要なのは、単にzhを2つのタグへ置き換えることではありません。アプリが必要としているのが「中国語という言語の判定」なのか、「繁体字と簡体字の区別」なのかを整理し、それぞれに適した粒度で言語タグを扱うことです。

既存コードでは、まずzhとの完全一致、2文字固定のバリデーション、翻訳先の対応表、データベースの列長を確認してください。内部では新しい言語タグを保持し、古い形式が必要な外部連携だけを変換する設計にすると、互換性を保ちながらEdge 151の改善を活用できます。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次