$30 off During Our Annual Pro Sale. View Details »

Intlの今までとこれから

Saji
November 18, 2023

 Intlの今までとこれから

JSConf JP 2023 : 2023/11/19
- https://jsconf.jp/2023/talk/ryusei-sajiki-1/

Saji

November 18, 2023
Tweet

More Decks by Saji

Other Decks in Technology

Transcript

  1. 3ZVTFJ4BKJLJ!TBKJLJY
    *OUMͷࠓ·Ͱͱ͜Ε͔Β

    View Slide

  2. 4BKJ3ZVTFJ4BKJLJ
    'SPOUFOE%FWFMPQFSBU$ZCP[V JOD
    𝕏
    !TBKJLJY

    View Slide

  3. ΞδΣϯμ
    *OUMͱ͸
    *OUMࡦఆ·Ͱͷྺ࢙
    *OUMͷ͜Ε·ͰͷਐԽɾαϙʔτ
    *OUMʹؔ࿈͢Δ࢓༷ͨͪ
    *OUMͷ͜Ε͔Β

    View Slide

  4. *OUMͱ͸

    View Slide

  5. 8IBUJT*OUM࢓༷ॻʹΑΔͱ
    This Standard de
    fi
    nes the application programming interface for ECMAScript
    objects that support programs that need to adapt to the linguistic and cultural
    conventions used by different human languages and countries.(from
    ECMA-402, 10th
    edition)
    ͜ͷඪ४͸ɺҟͳΔਓؒͷݴޠ΍ࠃͰ࢖༻͞ΕΔݴޠతɾจԽతͳ׳शʹదԠ
    ͢Δඞཁͷ͋ΔϓϩάϥϜΛαϙʔτ͢ΔECMAScriptΦϒδΣΫτͷΞϓϦέ
    ʔγϣϯϓϩάϥϛϯάΠϯλϑΣʔεΛఆٛ͢Δɻ

    View Slide

  6. ΋͏ͪΐͬͱ۩ମతʹ
    +BWB4DSJQUͷࠃࡍԽ"1*ͷ໊લۭؒ Intl.ʓʓ

    ҎԼͷΑ͏ʹݴޠʹґଘͨ͠ػೳΛఏڙ͢Δ
    w ೔࣌ɾ਺஋ͷϑΥʔϚοτ
    w ϩέʔϧͷղܾ
    w ݴޠʹґଘͨ͠จࣈྻͷൺֱ
    w ςΩετ۠੾Γɾෳ਺ܗͷ൑ผ

    View Slide

  7. *OUMͷ࢓༷తͳҐஔ෇͚
    +BWB4DSJQUͷ࢓༷Ͱ͋Δ&$."ͷʮ֦ு࢓༷ʯͱ͍͏Ґஔ෇͚ɻ
    &$."ͱ͸۠ผͯ͠&$."ͱ͍͏࢓༷൪߸͕͍͍ͭͯΔɻ
    1SPQPTBMͷ؅ཧ΍ձٞʹ΋෼͚ͯਐΊΒΕ͍ͯΔ
    &$."
    &$."
    *OUM

    ࣗ෼͕ͨͪ+BWB4DSJQUͷ࢓༷ͱଊ͍͑ͯΔ΋ͷ

    View Slide

  8. ࢖͍ํͱ֤"1*Λͬ͘͟Γ঺հ

    View Slide

  9. *OUMͷ"1*֓ཁ
    *OUM͸̎ͭͷϝιουͱͭ̕ͷίϯετϥΫλϓϩύςΟΛ͍࣋ͬͯΔ
    w ϝιου͸ิॿతͳ΋ͷͰϝΠϯͷػೳ͸ίϯετϥΫλϓϩύςΟܦ༝
    Α͘࢖͏ίϯετϥΫλϓϩύςΟ

    ✨Intl.DateTimeFormat()



    ✨Intl.NumberFormat()


    • Intl.RelativeTimeFormat() / Intl.Segmenter() /
    Intl.PluralRules()

    View Slide

  10. *OUMͷ"1*֓ཁ
    શͯͷίϯετϥΫλϓϩύςΟ͸MPDBMFͱ0QUJPOͷ̎ͭΛҾ਺ʹऔΔ
    w -PDBMF࢖༻͢ΔMPDBMFɻݴޠλά͔-PDBMFΦϒδΣΫτͰࢦఆɻ
    w ྫ“ja-JP”, “en-US”
    w 0QUJPOGPSNBUͳͲʹ͓͚ΔΦϓγϣϯɻ
    w ྫ{calender : "japanese"} ࢖༻͢ΔྐྵΛ࿨ྐྵʹ͢Δ

    ίϯετϥΫλΛॳظԽ͢ΔࡍʹϩέʔϧͱϑΥʔϚοτͳͲͷΦϓγϣϯΛࢦ
    ఆ͢Δͷ͕ϙΠϯτ

    View Slide

  11. ࢖͍ํͷྫ
    const formatter = new Intl.NumberFormat("en", {


    notation: "compact",


    compactDisplay: "long",


    });


    formatter.format(123456789);
    શମ૾

    View Slide

  12. ࢖͍ํͷྫ
    const formatter = new Intl.NumberFormat("en", {


    notation: "compact",


    compactDisplay: "long",


    });


    formatter.format(123456789);
    ϩέʔϧͷࢦఆ

    View Slide

  13. ࢖͍ํͷྫ
    const formatter = new Intl.NumberFormat("en", {


    notation: "compact",


    compactDisplay: "long",


    });


    formatter.format(123456789);
    Φϓγϣϯͷࢦఆ

    View Slide

  14. ࢖͍ํͷྫ
    const formatter = new Intl.NumberFormat("en", {


    notation: "compact",


    compactDisplay: "long",


    });


    formatter.format(123456789);
    ίϯετϥΫλϓϩύςΟΛOFX

    View Slide

  15. ࢖͍ํͷྫ
    const formatter = new Intl.NumberFormat("en", {


    notation: "compact",


    compactDisplay: "long",


    });


    formatter.format(123456789);
    ࣮ࡍʹGPSNBUϝιουΛݺͼग़͢

    View Slide

  16. ࢖͍ํͷྫ
    const formatter = new Intl.NumberFormat("en", {


    notation: "compact",


    compactDisplay: "long",


    });


    formatter.format(123456789); // → 123 million
    ϑΥʔϚοτ͞ΕΔʂ

    View Slide

  17. Α͘࢖͏ػೳ*OUM%BUF5JNF'PSNBU
    ݴޠ͝ͱʹҟͳΔ೔࣌ͷϑΥʔϚοτΛߦ͏
    format()ϝιουͱformatRange()ϝιουΛ࣋ͭ
    w format()“12/07/2015”


    w formatRange()“12/07/2015 ~ 12/09/2015”


    ͦΕͧΕ“ToParts”ͷ͍ͭͨόʔδϣϯͷϝιου΋͋Δ
    • formatToParts() / formatRangeToParts()


    w ϑΥʔϚοτจࣈྻΛҙຯ͝ͱʹ۠੾ͬͨ഑ྻͰग़ྗͯ͘͠ΕΔ

    View Slide

  18. *OUM%BUF5JNF'PSNBUͷ࢖༻ྫ
    const formatter = Intl.DateTimeFormat('en-US', {


    dateStyle: 'short'


    });


    const date = new Date(Date.UTC(2023, 10, 19));


    formatter.format(date); // → 11/19/23


    formatter.formatToParts(date);


    // [


    // { type: 'month', value: '11' },


    // { type: 'literal', value: '/' },


    // { type: 'day', value: ’19' },


    // { type: 'literal', value: '/' },


    // { type: 'year', value: '23' }


    // ];

    View Slide

  19. Α͘࢖͏ػೳ*OUM/VNCFS'PSNBU
    ७ਮͳ਺஋͚ͩͰͳ͘୯Ґ΍௨՟ɺύʔηϯτΛؚΜͩ਺஋ͷϑΥʔϚοτ
    w “decimal”ྫ
    “123.4”


    w “currency”ྫ
    “$123.4”
    w “percent”ྫ
    “123.4%”


    w “unit”ྫ
    “123.4km/h”
    ϝιου͸%BUF5JNF'PSNBUͱಉ༷
    w format()/formatRange()/formatToParts()/formatRangeToParts()

    View Slide

  20. *OUM/VNCFS'PSNBUͷ࢖༻ྫ ਺஋

    const compactFormatter = new Intl.NumberFormat('en', {


    style: 'decimal',


    notation: 'compact'


    });


    compactFormatter.format(1000000); // '1M'


    const FourDigitFormatter = new Intl.NumberFormat('en', {


    style: 'decimal',


    maximumSignificantDigits: 4


    });


    FourDigitFormatter.format(123.456); // "123.5"

    View Slide

  21. *OUM/VNCFS'PSNBUͷ࢖༻ྫ ௨՟

    const enFormatter = new Intl.NumberFormat("en", {


    style: "currency",


    currency: "USD",


    });


    enFormatter.format(12345); // “$12,345.00”


    const jaFormatter = new Intl.NumberFormat("ja", {


    style: “currency",


    currency: "JPY",


    });


    jaFormatter.format(12345); // “ˇ12,345”

    View Slide

  22. *OUM/VNCFS'PSNBUͷ࢖༻ྫ ୯Ґ

    const formatter = new Intl.NumberFormat("en", {


    style: "unit",


    unit: "foot",


    unitDisplay: "long",


    });


    formatter.format(1); // → 1 foot


    formatter.format(2); // → 2 feet

    View Slide

  23. ଞʹ΋͋Δ*OUMͷศརͳػೳ
    Intl.RelativeTimeFormat()


    w ʮ໌೔ʯ΍ʮ͓ͱͱ͍ʯͷΑ͏ͳ૬ରతͳ೔࣌දهͷࠃࡍԽΛߦ͏
    Intl.Segmenter()


    w จࣈɾ୯ޠɾจ͝ͱͷ෼ͪॻ͖Λߦ͏
    Intl.PluralRules()


    w ݴޠ͝ͱͷෳ਺ܗϧʔϧ෼ྨ΍ং਺ TU OEʜ
    Λฦ͢

    View Slide

  24. ͦΜͳ*OUMɺ
    ࣮͸ྺ࢙͕௕͍ΜͰ͢

    View Slide

  25. *OUMࡦఆ·Ͱͷྺ࢙

    View Slide

  26. ḪΔ͜ͱ೥લ

    View Slide

  27. UINFFUJOHPG5$

    (PPHMFͷ/FCPKãB㶎JSJ㶛ࢯͱ+VOHTIJL4IJOࢯʹΑͬͯఏҊ͞Εͨ

    View Slide

  28. ࡦఆ։࢝౰࣌ʹ͓͚Δ՝୊ײ
    🤔&$."4DSJQU͸ࠃࡍԽػೳΛݶఆతʹ͔͠αϙʔτ͍ͯ͠ͳ͔ͬͨ
    w Date.toLocaleString()ͷΑ͏ͳॳาతͳιʔτ΍ϑΥʔϚοτػೳͷΈ
    🤔จࣈྻιʔτͷ࣮૷͕ϒϥ΢βʹΑͬͯҟͳΔ
    w ϒϥ΢βؒͰͷ&$."4DSJQUΤϯδϯͷ࣮૷͕·ͪ·ͪ

    View Slide

  29. *OUMࡦఆલʹߟ͑ΒΕͯͨղܾํ๏ͱ໰୊఺
    ೔෇΍௨՟ΛϑΥʔϚοτ͢Δઐ༻ͷJOϥΠϒϥϦΛ࣮૷ˠγϯάϧϩ
    έʔϧσʔλʹόϯυϧ
    w 👎ϥΠϒϥϦͷαΠζͱҰ؏ੑͷͳ͍"1*
    w 👎ࣅͨػೳͷϥΠϒϥϦΛॏෳͯ͠Πϯετʔϧ͢Δ͜ͱʹͳΔՄೳੑ
    αʔόʔ্Ͱ͢΂ͯͷࠃࡍԽॲཧΛߦ͍ɺ݁ՌΛૹ৴͢Δɻ
    w 👎஗Ԇ͢Δ্ʹΦϯϥΠϯΞΫηεͱࠃࡍԽॲཧΛߦ͏αʔόʔ͕ඞཁ

    View Slide

  30. Ұ؏ͨ͠&$."4DSJQU"1*
    Ͱղܾͩʂ

    View Slide

  31. ࠃࡍԽ"1*ࡦఆʹΑͬͯͰ͖Δ͜ͱ
    👍Ұ؏ͨ͠ࠃࡍԽ݁ՌΛฦͤΔ
    w $-%3΍ओཁͳϓϥοτϑΥʔϜͷϩέʔϧαϙʔτͱಉϨϕϧ
    👍ΞϓϦέʔγϣϯ͝ͱʹෳ਺ͷϩέʔϧΛαϙʔτͰ͖Δ
    w ϩέʔϧࣝผࢠ͸6OJDPEFඪ४ʹै͏
    👍౷Ұ͞Εͨ"1*ʹΑΓίʔυ಺ͰΦϒδΣΫτͷ࠶ར༻͕͠΍͘͢ͳΔ
    w ࡞੒ίετͷߴ͍ΦϒδΣΫτͩͱಛʹԸܙ͕͋Δ

    View Slide

  32. ࠃࡍԽ"1*ࡦఆʹΑͬͯͰ͖Δ͜ͱ
    αʔόʔ্ͰࠃࡍԽΛߦ͏Θ͚Ͱ͸ͳ͍ͷͰʜ
    👍αʔόʔ΁ͷݺͼग़͕͠ͳ͍ͨΊɺ଴͕ͪ࣌ؒͳ͍ɻ
    👍ΦϑϥΠϯॲཧ΋࣮ݱͰ͖Δ
    ඪ४ػೳͷ"1*ͳͷͰʜ
    👍ϖʔδ΍ΤΫεςϯγϣϯͷαΠζ͕૿Ճ͠ͳ͍

    View Slide

  33. ॳ൛׬੒·ͰͷಓͷΓ
    *OUMͷݩͱͳΔఏҊ͕5$ͷ.FFUJOHͰ͞ΕΔ
    ࠷ॳͷࠃࡍԽ"1*.FFUJOH͕։࠵
    4USBXNBOQSPQPTBMW͕ެ։
    ೥݄Ͱͷ࢓༷ࡦఆΛ໨ࢦ͢͜ͱʹͳΔ
    ୈdճͷࠃࡍԽ.FFUJOH ໊લۭؒͷ౷Ұɾػೳͷ࡟ݮɾपล࢓༷ͱͷௐ੔FUD

    ࠷ॳͷ%SBGU4QFD ͜ͷลΓͰ͋Δఔ౓࢓༷ΛݻΊΔ

    ࠷ޙͷ%SBGU4QFDJ
    fi
    DBUJPO
    %SBGU4QFDͷվળ࡞ۀɾ࣮૷࡞ۀ ໊લۭؒͷ໊લมߋɾ"1*ͷमਖ਼FUD

    View Slide

  34. ͦͯ͠೥݄

    View Slide

  35. TU&EJUJPOެ։ʂ🎉

    View Slide

  36. TU&EJUJPOͷ֓ཁ
    ఆٛ͞ΕͨίϯετϥΫλϓϩύςΟ͸̏ͭ
    w *OUM$PMMBUPS
    w *OUM/VNCFS'PSNBU
    w *OUM%BUF5JNF'PSNBU
    طଘͷ࣮૷ͱͷ౷߹
    w /VNCFSUP-PDBM4USJOH%BUFUP-PDBM4USJOHͷ֦ு

    View Slide

  37. ݱࡏͷػೳͱൺ΂Δͱ
    ݁ߏγϯϓϧ

    View Slide

  38. *OUMͷ͜Ε·ͰͷਐԽ

    View Slide

  39. ࡦఆޙͷϒϥ΢βαϙʔτ

    View Slide

  40. ೥ TU&EJUJPOࡦఆ͔Β೥

    $ISPNF *& 'JSFGPY 4BGBSJ
    %BUF5JNF'PSNBU
    ⚪︎
    ˚ º º
    /VNCFS'PSNBU
    ⚪︎
    ˚ º º
    $PMMBUPS
    ⚪︎
    ˚ º º

    View Slide


  41. $ISPNF *& 'JSFGPY 4BGBSJ
    %BUF5JNF'PSNBU
    ⚪︎
    ˚
    ⚪︎
    º
    /VNCFS'PSNBU
    ⚪︎
    ˚
    ⚪︎
    º
    $PMMBUPS
    ⚪︎
    ˚
    ⚪︎
    º

    View Slide


  42. $ISPNF *&ˠ&EHF 'JSFGPY 4BGBSJ
    %BUF5JNF'PSNBU
    ⚪︎
    ⚪︎
    ⚪︎
    º
    /VNCFS'PSNBU
    ⚪︎
    ⚪︎
    ⚪︎
    º
    $PMMBUPS
    ⚪︎
    ⚪︎
    ⚪︎
    º

    View Slide


  43. $ISPNF *&ˠ&EHF 'JSFGPY 4BGBSJ
    %BUF5JNF'PSNBU
    ⚪︎
    ⚪︎
    ⚪︎
    ⚪︎
    /VNCFS'PSNBU
    ⚪︎
    ⚪︎
    ⚪︎
    ⚪︎
    $PMMBUPS
    ⚪︎
    ⚪︎
    ⚪︎
    ⚪︎

    View Slide

  44. ೥ɺॳ൛ͰఏҊ͞Εͨ
    "1*܈͕Ұ௨Γ࢖͑ΔΑ͏ʹ
    🎉

    View Slide

  45. ػೳ໘΋ਐԽͯ͠·͢

    View Slide

  46. ݱࡏͷ*OUM͸UI&EJUJPO
    OE&EJUJPO͕೥ɾͦͷޙ͸ຖ೥ࡦఆ

    View Slide

  47. OE&EJUJPOҎ߱ͷ
    ػೳ௥ՃΛݟ͍ͯ͘

    View Slide

  48. OE&EJUJPO

    େ͖ͳػೳ௥Ճͱ͍͏ΑΓपล࢓༷΍&4ͱͷڠௐ͕ϝΠϯ
    w &4ͱͷڠௐ
    w Array.toLocaleString()Λ௥Ճ
    w *"/"5JNF[POF/BNFΛड͚෇͚ΔΑ͏ʹ

    View Slide

  49. SE&EJUJPO

    Intl.getCanonicalLocales();


    // ॏෳ͕লུ͞Εɺ༗ޮͳݴޠλάͷ഑ྻΛฦ͢


    console.log(Intl.getCanonicalLocales("EN-US"));


    // Array [“en-US"]


    console.log(


    Intl.getCanonicalLocales(["EN-US", "Fr"]),


    );


    // Array ["en-US", "fr"]

    View Slide

  50. UI UI&EJUJPO

    formatToParts() (DateTimeFormat / NumberFormat)


    // ҙຯ͝ͱʹformatจࣈྻΛ෼ׂͨ͠഑ྻͱͯ͠ฦ͢


    const formatter = Intl.DateTimeFormat('en-US', {});


    formatter.formatToParts(new Date(Date.UTC(2023, 10, 19)));


    // [


    // { type: 'month', value: '11' },


    // { type: 'literal', value: '/' },


    // { type: 'day', value: ’19' },


    // { type: 'literal', value: '/' },


    // { type: 'year', value: '23' }


    // ];

    View Slide

  51. UI&EJUJPO

    Intl.PluralRules


    // ং਺΍ෳ਺ܗͷϧʔϧΛ൑ผ͢Δػೳͷ௥Ճ


    const pluralRule = new Intl.PluralRules("en-US", {


    type: "ordinal",


    });


    pluralRule.select(1); // → "one" : 1st


    pluralRule.select(2); // → "two" : 2nd


    pluralRule.select(3); // → "few" : 3rd


    pluralRule.select(13); // → "other" : 13th


    pluralRule.select(103); // → "few" : 103rd

    View Slide

  52. UI&EJUJPO

    Intl.RelativeTimeFormat
    // ʮࡢ೔ʯͷΑ͏ͳ૬ରతͳ೔࣌දهͷϑΥʔϚοτ


    const rtfEn = new Intl.RelativeTimeFormat("en", {


    numeric: "auto",


    });


    rtfEn.format(1, "day"); // "tomorrow"


    const rtfJa = new Intl.RelativeTimeFormat("ja", {


    numeric: "auto",


    });


    rtfJa.format(2, "day"); // "໌ޙ೔"

    View Slide

  53. UI&EJUJPO

    Intl.Locale Object
    // ϩέʔϧ৘ใΛΑΓ؆୯ʹૢ࡞ɾ؅ཧͰ͖Δ


    const korean = new Intl.Locale("ko", {


    script: "Kore",


    region: "KR",


    hourCycle: "h23",


    calendar: "gregory",


    });


    console.log(korean.hourCycle); // "h23"

    View Slide

  54. UI&EJUJPO

    Intl.ListFormat
    // ݴޠΛߟྀͨ͠Ϧετ(and/orͰͲ͏ܨ͙͔)ͷϑΥʔϚοτ


    const languages = ['JavaScript', 'JavaScript', 'HTML'];


    const formatter = new Intl.ListFormat('en', {


    style: 'long',


    type: 'conjunction',


    });


    console.log(formatter.format(languages));


    // "JavaScript, JavaScript, and HTML"

    View Slide

  55. UI&EJUJPO

    Intl.DisplayNames


    // ݴޠ໊ɺ஍Ҭ໊ɺจࣈମܥ໊ࣗମͷදࣔΛࠃࡍԽ


    const regionNamesInJapanese = new Intl.DisplayNames(


    ["ja"],


    { type: "language" },


    );


    regionNamesInJapanese.of("en"); // “ӳޠ”


    regionNamesInJapanese.of("ja"); // “೔ຊޠ"

    View Slide

  56. UI&EJUJPO

    DateTimeFormat:formatRange()
    // ೔࣌ͷظؒදهͷϑΥʔϚοτΛߦ͏


    const formatter = Intl.DateTimeFormat('en-US', {


    dateStyle: 'short'


    });


    const dateStart = new Date(Date.UTC(2023, 10, 18));


    const dateEnd = new Date(Date.UTC(2023, 10, 19));


    formatter.formatRange(dateStart, dateEnd);


    // '11/18/23 – 11/19/23'

    View Slide

  57. UI&EJUJPO

    'dayStyle','timeStyle' in DateTimeFormat
    // ҙຯ͝ͱʹformatจࣈྻΛ෼ׂͨ͠഑ྻͱͯ͠ฦ͢


    const dateFormatter = Intl.DateTimeFormat("en-US", {


    dateStyle: "short",


    });


    const timeFormatter = Intl.DateTimeFormat("en-US", {


    timeStyle: "long",


    });


    const date = new Date(Date.UTC(2023, 10, 19))


    dateFormatter.format(date); // “11/19/23"


    timeFormatter.format(date); // "9:00:00 AM GMT+9"

    View Slide

  58. UI&EJUJPO

    Intl.Segmenter
    // จࣈɾ୯ޠɾจ͝ͱͷ෼ͪॻ͖Λߦ͏


    const segmenter = new Intl.Segmenter("ja-JP",


    { granularity: "word" },


    );


    console.log([...segmenter.segment("ޗഐ͸ೣͰ͋Δɻ")]);


    // [


    // {"segment": "ޗഐ", "index": 0, "isWordLike": true},


    // {"segment": "͸", "index": 2, "isWordLike": true},


    // ...(ུ)

    View Slide

  59. UI&EJUJPO

    Intl.DisplayNames v2
    // ΧϨϯμʔ໊ɺ೔࣌ͷϥϕϧ໊ࣗମͳͲͷදࣔΛࠃࡍԽ


    const calendarNamesInJapanese = new Intl.DisplayNames(


    ["ja"], { type: "calendar" },


    );


    calendarNamesInJapanese.of("japanese"); // “࿨ྐྵ”


    const dateTimeNamesInJapanese = new Intl.DisplayNames(


    ["ja"], { type: "dateTimeField" },


    );


    dateTimeNamesInJapanese.of("dayPeriod"); // “ޕલ/ޕޙ”

    View Slide

  60. UI&EJUJPO

    Intl Enumeration API
    // ͦͷ࣮૷Ͱαϙʔτ͞Ε͍ͯΔྐྵɺর߹ॱংɺͳͲͷ഑ྻΛฦ͢


    Intl.supportedValuesOf("calendar");


    // ['buddhist', 'chinese', 'coptic', ‘dangi’, …];


    Intl.supportedValuesOf("currency");


    // [‘AED', 'AFN', 'ALL', 'AMD', 'ANG', 'AOA', ‘ARS’, …]


    Intl.supportedValuesOf("numberingSystem");


    // [‘adlm', 'ahom', 'arab', 'arabext', 'bali', …]


    Intl.supportedValuesOf("timeZone");


    // ['Africa/Abidjan', 'Africa/Accra', …]

    View Slide

  61. UI&EJUJPO

    Intl.NumberFormat v3
    // formatRange()ϝιουͷαϙʔτ


    const formatter = new Intl.NumberFormat('en', {


    style: 'decimal',


    });


    formatter.formatRange(100, 200); // ‘100-200’


    // ਺஋ͷؙΊΦϓγϣϯͳͲͷॆ࣮


    const compactFormatter = new Intl.NumberFormat('en', {


    style: ‘decimal', maximumFractionDigits: 0


    });


    compactFormatter.formatR(3.14); // ‘3’

    View Slide

  62. TU&EJUJPOd·Ͱͷػೳ௥Ճ
    + Intl.getCanonicalLocales()


    + Intl.ListFormat


    + Intl.Segmenter


    + Intl.DisplayNames


    + Intl.PluralRules


    + Intl.RelativeTimeFormat


    + Intl.Locale


    + formatToParts()
    + formatRange()


    + DateTimeFormat option


    + NumberFormat option(v3)


    … and more


    View Slide

  63. ௥Ճ͞Εͨػೳͷαϙʔτ

    View Slide

  64. ݱࡏͷαϙʔτঢ়گ
    $ISPNF &EHF 'JSFGPY 4BGBSJ
    %BUF5JNF'PSNBU
    /VNCFS'PSNBU
    4FHNFOUFS º
    1MVSBM3VMFT
    3FMBUJWF5JNF'PSNBU

    View Slide

  65. ݱࡏͷαϙʔτঢ়گ
    $ISPNF &EHF 'JSFGPY 4BGBSJ
    1MVSBM3VMFT
    -PDBMF0CKFDU
    -JTU'PSNBU
    %JTQMBZ/BNFT

    View Slide

  66. 👍جຊతʹ͸αϙʔτ

    View Slide

  67. *OUMʹؔ࿈͢Δ࢓༷ͨͪ

    View Slide

  68. ؔ࿈࢓༷Λ஌Δҙຯ
    &DNB4DSJQUಠࣗͰܾΊΔΘ͚ʹ͸ߦ͚ͳͦ͞͏ͳ໰୊͕୔ࢁ
    w αϙʔτ͢Δจࣈ΍ͦͷιʔτ͸ʁ
    w αϙʔτ͢ΔλΠϜκʔϯ͸
    w ݴޠʹΑΔจ๏ࣄ߲ ෳ਺ܗͳͲʜ
    ͷ෼ྨͬͯʁ
    w ஍Ҭ΍ݴޠ໊Ͳ͏΍ͬͯ؅ཧ͢Δʁ
    ˠ*OUM͸ࠃࡍԽػೳͱ͍͏ੑ্࣭ɺଞͷඪ४࢓༷Λࢀর͢Δ෦෼͕ଟ͍

    View Slide

  69. *OUMͱͷؔ࿈࢓༷શମ૾
    *OUM
    *&5'
    #$1
    *"/"
    5JNF[POF

    *40
    ௨՟ίʔυ

    6OJDPEF
    -%.-
    $-%3

    View Slide

  70. *OUMͱͷؔ࿈࢓༷6OJDPEF
    ҎԼ͸6OJDPEFͷ࢓༷ʹ४ڌ͍ͯ͠Δ
    w จࣈηοτ
    w จࣈྻͷ۠੾Γʹؔ͢Δ࢓༷
    w 6OJDPEF4UBOEBSE"OOFY6OJDPEF5FYU4FHNFOUBUJPO
    w จࣈࣗମͷൺֱɾฒͼସ͑ʹؔ͢Δ࢓༷
    w 6OJDPEF5FDIOJDBM4UBOEBSE6OJDPEF$PMMBUJPO"MHPSJUIN

    View Slide

  71. *OUMͱͷؔ࿈࢓༷ͦ΋ͦ΋-%.-$-%3ͱ͸
    -%.- 6OJDPEF-PDBMF%BUB.BSLVQ-BOHVBHF

    w ߏ଄Խ͞ΕͨϩέʔϧσʔλΛަ׵͢ΔͨΊͷ9.-ϑΥʔϚοτ
    $-%3 $PNNPO-PDBMF%BUB3FQPTJUPSZ

    w ੈք֤஍ͷݴޠʹ͓͚Δ༷ʑͳϩέʔϧɾσʔλΛ·ͱΊͨϨϙδτϦ
    w -%.-ͷܗࣜʹͦͬͯهड़͞Ε͍ͯΔ

    View Slide

  72. *OUMͱͷؔ࿈࢓༷-%.-$-%3ͱ*OUM
    *OUM͸࢓༷ͷ֤ॴͰ-%.-४ڌͰ͋Δ͜ͱ͕໌ه͞Ε͍ͯΔ
    Intl.PluralRules


    w ෳ਺ܗͷύλʔϯɾϧʔϧ͸-%.-ͷݴޠෳ਺ϧʔϧʹ४ڌ
    Intl.ListFormat


    w ಺෦తͳσʔλͷܗࣜͱͯ͠-%.-ͷ-JTU1BUUFSOʹ४ڌ͢Δ͜ͱ
    -%.- ࢓༷
    ʹ४ڌ͢Δ͜ͱͰ$-%3 ϩέʔϧσʔλ
    Λ׆༻͠΍͘͢ͳΔ
    w ʮ࣮૷ʹ͓͍ͯ$-%3Λར༻͢Δ͜ͱʯΛ֤ॴͰਪ঑͍ͯ͠Δ

    View Slide

  73. *OUMͱͷؔ࿈࢓༷*&5' #$1

    *&5'ͷ#$1ݴޠλάͷ࢓༷
    *OUM͕αϙʔτ͢Δϩέʔϧจࣈྻ͸ͷ#$1ʹ४ڌ͍ͯ͠Δ
    #$1Ͱఆٛ͞Ε͍ͯΔ֦ுγʔέϯε΋*OUMͰ͸ར༻͢Δ
    w #$1֦ுγʔέϯε<จࣈ><dจࣈ><dจࣈ ೚ҙ
    >ͷܗͰλάΛ֦
    ுͰ͖Δ࢓༷
    w ݱࡏ*OUMͰղऍ͢Δͷ͸ͦͷதͷV 6OJDPEF
    ֦ு
    w ྫ
    ja-JP-u-ca-japanese u-ca-japaneseͷ෦෼

    View Slide

  74. *OUMͱͷؔ࿈࢓༷*"/"*40
    *"/"ͱͷؔ࿈
    w Intl.DateTimeFormatͰtimeZoneΦϓγϣϯʹࢦఆͰ͖Δ஋
    w *"/"λΠϜκʔϯσʔλϕʔεͷλΠϜκʔϯ໊
    *40ͱͷؔ࿈
    w Intl.NumberFormatͰcurrencyΦϓγϣϯʹࢦఆͰ͖Δ஋
    w *40ͷ௨՟ίʔυ

    View Slide

  75. *OUMͷ͜Ε͔Β

    View Slide

  76. طʹ͋ΔϓϩύςΟͷൃలɾॆ࣮
    Intl.NumberFormatW ઌड़

    w ਺஋ͷؙΊΛத৺ʹΦϓγϣϯΛେ෯ʹ௥Ճͨ͠ɻ
    Intl.SegmenterW 4UBHF

    w จࣈɾ୯ޠɾจʹՃ͑ͯվߦ۠੾ΓͷαϙʔτΛఏҊ͍ͯ͠Δ

    View Slide

  77. ఏҊ͞Ε͍ͯΔ৽͍͠ػೳͷ1SPQPTBM Ұ෦

    ࠓճ঺հ͢Δ΋ͷ
    w Intl Local Info API 4UBHF

    w Intl.DurationFormat 4UBHF

    w Intl.MessageFormat 4UBHF

    View Slide

  78. *OUM-PDBMF*OGP"1* 4UBHF

    ϩέʔϧ৘ใΛอ࣋͢ΔIntl.LocaleΦϒδΣΫτʹର༷ͯ͠ʑͳσʔλΛऔ
    ಘͰ͖ΔϝιουΛ௥Ճ͢ΔఏҊ
    w ྫ
    ʮจࣈΛॻ͘ํ޲ʯ΍ʮि࢝·Γʹ͍ͭͯͷ৘ใʯͳͲ
    const enGB = new Intl.Locale('en-GB');


    enGB.getWeekInfo();


    // {firstDay: 1, weekend: [6, 7], minimalDays: 4}


    let tl = enGB.getTextInfo();


    // { direction: "rtl" }

    View Slide

  79. *OUM%VSBUJPO'PSNBU
    ࣌ؒͷִؒදهΛϑΥʔϚοτ͢ΔػೳͷఏҊ
    w ྫ
    ࣌ؒ෼IPVSNJOVUFT
    new Intl.DurationFormat("fr-FR", {


    style: "long",


    }).format({


    hours: 1,


    minutes: 46,


    seconds: 40,


    });


    // => "1 heure, 46 minutes et 40 secondes"

    View Slide

  80. *OUM.FTTBHF'PSNBUલఏ஌ࣝ
    *$6 *OUFSOBUJPOBM$PNQPOFOUTGPS6OJDPEF
    ͱ͸
    w 6OJDPEF͕ϝϯςφϯε͍ͯ͠ΔࠃࡍԽͱ஍ҬԽʹؔ͢ΔϥΠϒϥϦ
    w ϑΥʔϚοτʹݶΒͣଟ͘ͷࠃࡍԽʹඞཁͳػೳΛ಺ଂ͍ͯ͠Δ
    *$6.FTTBHF'PSNBUʹ͍ͭͯ
    w *$6Ͱར༻͞Ε͍ͯΔϝοηʔδࠃࡍԽͷͨΊͷ'PSNBU
    w ϝοηʔδͷϓϨΠεϗϧμʔ΍จ๏ʹΑΔ৚݅෼ذͳͲΛදݱՄೳ

    View Slide

  81. *OUM.FTTBHF'PSNBU
    *$6.FTTBHF'PSNBUΛղऍ͠ɺͦΕʹ४ڌͯ͠ϑΥʔϚοτ͢ΔػೳͷఏҊ
    ݱঢ়ಠࣗͷϝοηʔδϑΥʔϚοτ࢓༷͕ଟ͍
    w 👎ΞϓϦέʔγϣϯଆͰ΋ಠࣗͷղੳॲཧ͕ඞཁʹͳΔ
    *$6.FTTBHF'PSNBUΛαϙʔτ͢Δͱʜ
    w 👍ΞϓϦέʔγϣϯຖʹϑΥʔϚοτͷղੳॲཧ͸͍Βͳ͘ͳΔ
    w 👍ۀքඪ४ͷπʔϧ΍ϓϩηεΛ࢖༻ͨ͠ϩʔΧϥΠζ͕༰қʹͳΔ

    View Slide

  82. *OUM.FTTBHF'PSNBUྫ
    const source = ... // ্ͷϑΥʔϚοτจࣈྻ


    const mf = new Intl.MessageFormat(source, 'en');


    const notifications = mf.format({ count: 1 });


    // 'You have 1 new notification'
    match {$count :number}


    when 0 {You have no new notifications}


    when one {You have {$count} new notification}


    when * {You have {$count} new notifications}
    *$6ͷϑΥʔϚοτจࣈྻ .FTTBHF'PSNBUW

    View Slide

  83. ଞͷ1SPQPTBMͱͷڠௐ

    View Slide

  84. 5FNQPSBMͱͷڠௐ5FNQPSBMͱ͸
    Temporalͱ͸
    w &$."4DSJQUͰ೔࣌Λૢ࡞͢ΔͨΊͷ৽͍͠"1*܈
    w ݱࡏ4UBHFͷ1SPQPTBM
    ೔࣌ͷϑΥʔϚοτ΍αϙʔτ͢ΔΦϓγϣϯͳͲͰTemporalͱؔ࿈͢Δ
    ˠTemporalଆͰ*OUMʹ४ڌͨ͠࢓༷ࡦఆ͕ਐΊΒΕ͍ͯΔ

    View Slide

  85. 5FNQPSBMͱͷڠௐ
    Temporal͸*OUMΛલఏͱͯ͠"1*Λઃܭ͍ͯ͠Δ
    w TemporalͷtoLocaleString()͸Intl.DateTimeFormatͱಉ͡Ҿ਺
    w Temporal.CalendarͰରԠ͢ΔΧϨϯμʔ͸Intl.DateTimeFormatͰα
    ϙʔτ͢Δ΋ͷͱҰॹ
    w ΧϨϯμʔͷղܾͳͲ͸*OUMଆͷ࢓༷Λࢀর͍ͯ͠Δ
    w Temporal.Duration͸Intl.DurationFormat TUBHF
    ͱಉ͡0QUJPOʹ
    ͳΔ༧ఆ

    View Slide

  86. 🤩ࠓޙΑΓศརʹ

    View Slide

  87. ·ͱΊ

    View Slide

  88. ·ͱΊ
    w *OUM͸਺஋೔࣌ͷϑΥʔϚοτʹݶΒͣݴޠʹґଘ༷ͨ͠ʑͳػೳΛఏڙ͢Δ
    w *OUMͷྺ࢙͸ݹ͘೥ۙ͘લ͔Β࢓༷ͷࡦఆͱαϙʔτ͕ঃʑʹਐΜͰ͖ͨ
    w ೥ݱࡏɺجຊతͳػೳͷ΄ͱΜͲΛ֤ϒϥ΢β͕αϙʔτ͍ͯ͠Δ
    w *OUM͸6OJDPEFΛ͸͡Ίͱ͢Δपล࢓༷ͱͷ࿈ܞ΋ີʹ࣮ͯ͠૷͞Ε͍ͯΔ
    w ࠓޙ΋৽͍͠ػೳ͕௥Ճ͞ΕΔ༧ఆͰ͋Γɺ5FNQPSBMͷΑ͏ͳ৽͍͠࢓༷ͷ
    ఏҊͱ΋ڠௐ͍ͯ͘͠
    w ࠓͦ͜*OUMΛ࢖͍͜ͳ࣌͢ʂ

    View Slide

  89. 3ZVTFJ4BKJLJ!TBKJLJY
    ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View Slide