Upgrade to Pro — share decks privately, control downloads, hide ads and more …

「UIは英語なのにアプリ内リンクは日本語だ!」を防ぐコツ / pixiv App Night ...

FromAtom
October 24, 2024
62

「UIは英語なのにアプリ内リンクは日本語だ!」を防ぐコツ / pixiv App Night 2024-10-24

スマホアプリでは利用規約やプライバシーポリシーなど、静的URLを利用することがよくあります。特に多言語対応したアプリでは端末の言語によってアクセスするURLを変えたい場合がありますが、URLの指定ミスは見た目ではわかりにくく、クラッシュやエラーも発生しないため、問題に気づきにくい課題があります。

この課題を解決するためにString Catalogを利用して静的URLの翻訳を管理し、さらにそれをTestで検証できるようにしたノウハウについてお話します。

FromAtom

October 24, 2024
Tweet

More Decks by FromAtom

Transcript

  1. switch Locale.current.identifier { case "ja_JP": // ೔ຊޠURL case "en_US": //

    ӳޠURL default: // ͦͷଞݴޠURL } ύοͱࢥ͍࣮ͭ͘૷͸Locale.current • ରԠݴޠ͕૿͑ͨΒʁ • "en_JP" ΍ "ja_US" ͸ʁ
  2. enum ExternalStaticLinks: String, CaseIterable, Sendable { case helpPage = "HelpPageURL"

    public var localizationValue: String.LocalizationValue { .init(rawValue) } public var url: URL { .init(string: urlString)! } public var urlString: String { .init(localized: localizationValue) } } let url = ExternalStaticLinks.helpPage.url
  3. enum SupportLanguages: String, CaseIterable { case en = "en" case

    ja = "ja" var bundle: Bundle? { guard let path = Bundle.main.path(forResource: rawValue, ofType: "lproj") else { return nil } return Bundle(path: path) } } final class LinkLocalizeSampleTests: XCTestCase { func test_HelpページのURLが全言語で想定通りに返ってくる() throws { let localizationValue = ExternalStaticLinks.helpPage.localizationValue for lang in SupportLanguages.allCases { let urlString = String(localized: localizationValue, bundle: lang.bundle) switch lang { case .en: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-english") case .ja: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-japanese") } XCTAssertNotNil(URL(string: urlString)) } } }
  4. enum SupportLanguages: String, CaseIterable { case en = "en" case

    ja = "ja" var bundle: Bundle? { guard let path = Bundle.main.path(forResource: rawValue, ofType: "lproj") else { return nil } return Bundle(path: path) } } final class LinkLocalizeSampleTests: XCTestCase { func test_HelpページのURLが全言語で想定通りに返ってくる() throws { let localizationValue = ExternalStaticLinks.helpPage.localizationValue for lang in SupportLanguages.allCases { let urlString = String(localized: localizationValue, bundle: lang.bundle) switch lang { case .en: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-english") case .ja: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-japanese") } XCTAssertNotNil(URL(string: urlString)) } } }
  5. enum SupportLanguages: String, CaseIterable { case en = "en" case

    ja = "ja" var bundle: Bundle? { guard let path = Bundle.main.path(forResource: rawValue, ofType: "lproj") else { return nil } return Bundle(path: path) } } final class LinkLocalizeSampleTests: XCTestCase { func test_HelpページのURLが全言語で想定通りに返ってくる() throws { let localizationValue = ExternalStaticLinks.helpPage.localizationValue for lang in SupportLanguages.allCases { let urlString = String(localized: localizationValue, bundle: lang.bundle) switch lang { case .en: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-english") case .ja: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-japanese") } XCTAssertNotNil(URL(string: urlString)) } } } // => HelpPageURL
  6. enum SupportLanguages: String, CaseIterable { case en = "en" case

    ja = "ja" var bundle: Bundle? { guard let path = Bundle.main.path(forResource: rawValue, ofType: "lproj") else { return nil } return Bundle(path: path) } } final class LinkLocalizeSampleTests: XCTestCase { func test_HelpページのURLが全言語で想定通りに返ってくる() throws { let localizationValue = ExternalStaticLinks.helpPage.localizationValue for lang in SupportLanguages.allCases { let urlString = String(localized: localizationValue, bundle: lang.bundle) switch lang { case .en: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-english") case .ja: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-japanese") } XCTAssertNotNil(URL(string: urlString)) } } }
  7. enum SupportLanguages: String, CaseIterable { case en = "en" case

    ja = "ja" var bundle: Bundle? { guard let path = Bundle.main.path(forResource: rawValue, ofType: "lproj") else { return nil } return Bundle(path: path) } } final class LinkLocalizeSampleTests: XCTestCase { func test_HelpページのURLが全言語で想定通りに返ってくる() throws { let localizationValue = ExternalStaticLinks.helpPage.localizationValue for lang in SupportLanguages.allCases { let urlString = String(localized: localizationValue, bundle: lang.bundle) switch lang { case .en: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-english") case .ja: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-japanese") } XCTAssertNotNil(URL(string: urlString)) } } }
  8. enum SupportLanguages: String, CaseIterable { case en = "en" case

    ja = "ja" var bundle: Bundle? { guard let path = Bundle.main.path(forResource: rawValue, ofType: "lproj") else { return nil } return Bundle(path: path) } } final class LinkLocalizeSampleTests: XCTestCase { func test_HelpページのURLが全言語で想定通りに返ってくる() throws { let localizationValue = ExternalStaticLinks.helpPage.localizationValue for lang in SupportLanguages.allCases { let urlString = String(localized: localizationValue, bundle: lang.bundle) switch lang { case .en: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-english") case .ja: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-japanese") } XCTAssertNotNil(URL(string: urlString)) } } } default: ͸࢖Θͳ͍
  9. enum SupportLanguages: String, CaseIterable { case en = "en" case

    ja = "ja" var bundle: Bundle? { guard let path = Bundle.main.path(forResource: rawValue, ofType: "lproj") else { return nil } return Bundle(path: path) } } final class LinkLocalizeSampleTests: XCTestCase { func test_HelpページのURLが全言語で想定通りに返ってくる() throws { let localizationValue = ExternalStaticLinks.helpPage.localizationValue for lang in SupportLanguages.allCases { let urlString = String(localized: localizationValue, bundle: lang.bundle) switch lang { case .en: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-english") case .ja: XCTAssertEqual(urlString, "https://sites.google.com/view/url-l18n-demo/help-japanese") } XCTAssertNotNil(URL(string: urlString)) } } }