English

言語ごとのページ

言語は各ページのルートの最初のセグメントに置きます。そのため、別の言語のページは言語だけを変えた同じルートになります。

ルートに言語を入れる

Locale は Segment なので、"/{lang}/members/{id}" に対する Route<(Lang, i32)> のように、ルートの最初のパラメータにできます。ハンドラはほかのパラメータと一緒に言語を受け取ります。enum にない言語へのリクエストには、ハンドラを呼ぶ前に 404 を返します。

use hypersig::html::a;
use hypersig::{Page, Route};

#[derive(Signals, Serialize, Deserialize)]
struct Profile {
    name: String,
}

hypersig::routes! {
    fn pages(Router<()>);
    // The language is the first segment of every page.
    const MEMBER: Route<(Lang, i32)> = "/{lang}/members/{id}" => member;
}

async fn member((): (), (lang, id): (Lang, i32)) -> Page<Profile> {
    let other = if lang == Lang::En { Lang::Ja } else { Lang::En };
    Page::new(lang.pick(ByLang { en: "Member", ja: "メンバー" }), Profile { name: "Ada".to_owned() })
        .lang(lang.tag())
        // The same page in the other language is the same route with another locale.
        .child(a().href(MEMBER.link_with((&other, id))).text(other.pick(ByLang { en: "English", ja: "日本語" })))
}

assert_eq!(MEMBER.url((Lang::Ja, 7)).as_str(), "/ja/members/7");

同じページの別の言語へのリンクは、link_with に別の言語とそのほかの同じパラメータを渡して作ります。そのため、ほかのリンクと同じくルートがこのリンクを検査します。言語を切り替える UI は Locale::ALL を並べ、言語ごとに読者が今いるページへリンクします。

ページの言語

Page::lang はタグを <html lang> に書きます。ブラウザはこの属性を見て、ハイフネーション、スクリーンリーダーの読み上げの声、使うフォントを決めます。そのため、lang="ja" の付いた日本語の文は日本語の字形で表示されます。

LocalePage::alternates は Origin と、|lang| POST.url((lang, id)) のように言語からページの Url を返す関数を受け取ります。Locale::ALL の言語ごとに <link rel="alternate" hreflang> を 1 つ書き、最初の言語には x-default も書きます。検索エンジンはこれを見て、読者の言語のページを結果に出します。