diff --git a/client/src/i18n/TranslationContext.tsx b/client/src/i18n/TranslationContext.tsx index cb2a51754..81045346a 100644 --- a/client/src/i18n/TranslationContext.tsx +++ b/client/src/i18n/TranslationContext.tsx @@ -15,6 +15,7 @@ import ar from './translations/ar' import br from './translations/br' import cs from './translations/cs' import pl from './translations/pl' +import ja from './translations/ja' import { SUPPORTED_LANGUAGES, SupportedLanguageCode } from './supportedLanguages' export { SUPPORTED_LANGUAGES } @@ -23,7 +24,7 @@ type TranslationStrings = Record = { - de, en, es, fr, hu, it, ru, zh, 'zh-TW': zhTw, nl, id, ar, br, cs, pl, + de, en, es, fr, hu, it, ru, zh, 'zh-TW': zhTw, nl, id, ar, br, cs, pl, ja, } // Derived from SUPPORTED_LANGUAGES — add new languages there, not here. @@ -38,7 +39,7 @@ export function getLocaleForLanguage(language: string): string { export function getIntlLanguage(language: string): string { if (language === 'br') return 'pt-BR' - return ['de', 'es', 'fr', 'hu', 'it', 'ru', 'zh', 'zh-TW', 'nl', 'ar', 'cs', 'pl', 'id'].includes(language) ? language : 'en' + return ['de', 'es', 'fr', 'hu', 'it', 'ru', 'zh', 'zh-TW', 'nl', 'ar', 'cs', 'pl', 'id', 'ja' ].includes(language) ? language : 'en' } export function isRtlLanguage(language: string): boolean { diff --git a/client/src/i18n/supportedLanguages.ts b/client/src/i18n/supportedLanguages.ts index 458a9fff1..ace1a6c68 100644 --- a/client/src/i18n/supportedLanguages.ts +++ b/client/src/i18n/supportedLanguages.ts @@ -12,8 +12,9 @@ export const SUPPORTED_LANGUAGES = [ { value: 'zh', label: '简体中文', locale: 'zh-CN' }, { value: 'zh-TW', label: '繁體中文', locale: 'zh-TW' }, { value: 'it', label: 'Italiano', locale: 'it-IT' }, - { value: 'ar', label: 'العربية', locale: 'ar-SA' }, + { value: 'ar', label: 'العربية', locale: 'ar-SA' }, { value: 'id', label: 'Bahasa Indonesia', locale: 'id-ID' }, + { value: 'ja', label: '日本語', locale: 'ja-JP' }, ] as const export type SupportedLanguageCode = typeof SUPPORTED_LANGUAGES[number]['value'] diff --git a/client/src/i18n/translations/ja.ts b/client/src/i18n/translations/ja.ts new file mode 100644 index 000000000..289c1cd4a --- /dev/null +++ b/client/src/i18n/translations/ja.ts @@ -0,0 +1,2399 @@ +const ja: Record = { + // Common + 'common.save': '保存', + 'common.showMore': 'もっと見る', + 'common.showLess': '閉じる', + 'common.cancel': 'キャンセル', + 'common.clear': 'クリア', + 'common.delete': '削除', + 'common.edit': '編集', + 'common.add': '追加', + 'common.loading': '読み込み中…', + 'common.import': 'インポート', + 'common.select': '選択', + 'common.selectAll': 'すべて選択', + 'common.deselectAll': 'すべて解除', + 'common.error': 'エラー', + 'common.unknownError': '不明なエラー', + 'common.tooManyAttempts': '試行回数が多すぎます。時間をおいて再度お試しください。', + 'common.back': '戻る', + 'common.all': 'すべて', + 'common.close': '閉じる', + 'common.open': '開く', + 'common.upload': 'アップロード', + 'common.search': '検索', + 'common.confirm': '確認', + 'common.ok': 'OK', + 'common.yes': 'はい', + 'common.no': 'いいえ', + 'common.or': 'または', + 'common.none': 'なし', + 'common.date': '日付', + 'common.rename': '名前を変更', + 'common.name': '名前', + 'common.email': 'メールアドレス', + 'common.password': 'パスワード', + 'common.saving': '保存中…', + 'common.justNow': 'たった今', + 'common.hoursAgo': '{count}時間前', + 'common.daysAgo': '{count}日前', + 'common.saved': '保存しました', + 'trips.memberRemoved': '{username} を削除しました', + 'trips.memberRemoveError': '削除に失敗しました', + 'trips.memberAdded': '{username} を追加しました', + 'trips.memberAddError': '追加に失敗しました', + 'trips.reminder': 'リマインダー', + 'trips.reminderNone': 'なし', + 'trips.reminderDay': '日', + 'trips.reminderDays': '日', + 'trips.reminderCustom': 'カスタム', + 'trips.reminderDaysBefore': '出発前', + 'trips.reminderDisabledHint': '旅行のリマインダーは無効です。管理 > 設定 > 通知から有効にしてください。', + 'common.update': '更新', + 'common.change': '変更', + 'common.uploading': 'アップロード中…', + 'common.backToPlanning': 'プランに戻る', + 'common.reset': 'リセット', + 'common.expand': '展開', + 'common.collapse': '折りたたむ', + + // Navbar + 'nav.trip': '旅行', + 'nav.share': '共有', + 'nav.settings': '設定', + 'nav.admin': '管理', + 'nav.logout': 'ログアウト', + 'nav.lightMode': 'ライトモード', + 'nav.darkMode': 'ダークモード', + 'nav.autoMode': '自動', + 'nav.administrator': '管理者', + +// Dashboard + 'dashboard.title': 'マイ旅行', + 'dashboard.subtitle.loading': '旅行を読み込み中...', + 'dashboard.subtitle.trips': '{count}件の旅行({archived}件アーカイブ)', + 'dashboard.subtitle.empty': '最初の旅行を始めましょう', + 'dashboard.subtitle.activeOne': '進行中の旅行 {count}件', + 'dashboard.subtitle.activeMany': '進行中の旅行 {count}件', + 'dashboard.subtitle.archivedSuffix': ' · アーカイブ {count}件', + 'dashboard.newTrip': '新しい旅行', + 'dashboard.gridView': 'グリッド表示', + 'dashboard.listView': 'リスト表示', + 'dashboard.currency': '通貨', + 'dashboard.timezone': 'タイムゾーン', + 'dashboard.localTime': '現地', + 'dashboard.timezoneCustomTitle': 'カスタムタイムゾーン', + 'dashboard.timezoneCustomLabelPlaceholder': 'ラベル(任意)', + 'dashboard.timezoneCustomTzPlaceholder': '例:America/New_York', + 'dashboard.timezoneCustomAdd': '追加', + 'dashboard.timezoneCustomErrorEmpty': 'タイムゾーンIDを入力してください', + 'dashboard.timezoneCustomErrorInvalid': '無効なタイムゾーンです(例:Europe/Berlin)', + 'dashboard.timezoneCustomErrorDuplicate': 'すでに追加されています', + 'dashboard.emptyTitle': '旅行はまだありません', + 'dashboard.emptyText': '最初の旅行を作成して計画を始めましょう!', + 'dashboard.emptyButton': '最初の旅行を作成', + 'dashboard.nextTrip': '次の旅行', + 'dashboard.shared': '共有済み', + 'dashboard.sharedBy': '{name}さんが共有', + 'dashboard.days': '日数', + 'dashboard.places': '場所', + 'dashboard.members': '同行者', + 'dashboard.archive': 'アーカイブ', + 'dashboard.copyTrip': 'コピー', + 'dashboard.copySuffix': 'コピー', + 'dashboard.restore': '復元', + 'dashboard.archived': 'アーカイブ済み', + 'dashboard.status.ongoing': '進行中', + 'dashboard.status.today': '今日', + 'dashboard.status.tomorrow': '明日', + 'dashboard.status.past': '過去', + 'dashboard.status.daysLeft': '残り{count}日', + 'dashboard.toast.loadError': '旅行の読み込みに失敗しました', + 'dashboard.toast.created': '旅行を作成しました!', + 'dashboard.toast.createError': '旅行の作成に失敗しました', + 'dashboard.toast.updated': '旅行を更新しました!', + 'dashboard.toast.updateError': '旅行の更新に失敗しました', + 'dashboard.toast.deleted': '旅行を削除しました', + 'dashboard.toast.deleteError': '旅行の削除に失敗しました', + 'dashboard.toast.archived': '旅行をアーカイブしました', + 'dashboard.toast.archiveError': '旅行のアーカイブに失敗しました', + 'dashboard.toast.restored': '旅行を復元しました', + 'dashboard.toast.restoreError': '旅行の復元に失敗しました', + 'dashboard.toast.copied': '旅行をコピーしました!', + 'dashboard.toast.copyError': '旅行のコピーに失敗しました', + 'dashboard.confirm.delete': '旅行「{title}」を削除しますか?すべての場所と計画は完全に削除されます。', + 'dashboard.editTrip': '旅行を編集', + 'dashboard.createTrip': '新しい旅行を作成', + 'dashboard.tripTitle': 'タイトル', + 'dashboard.tripTitlePlaceholder': '例:日本の夏', + 'dashboard.tripDescription': '説明', + 'dashboard.tripDescriptionPlaceholder': 'この旅行について', + 'dashboard.startDate': '開始日', + 'dashboard.endDate': '終了日', + 'dashboard.dayCount': '日数', + 'dashboard.dayCountHint': '日付が未設定の場合に作成する日数です。', + 'dashboard.noDateHint': '日付未設定 — 既定で7日分が作成されます。後で変更できます。', + 'dashboard.coverImage': 'カバー画像', + 'dashboard.addCoverImage': 'カバー画像を追加(またはドラッグ&ドロップ)', + 'dashboard.addMembers': '同行者', + 'dashboard.addMember': 'メンバーを追加', + 'dashboard.coverSaved': 'カバー画像を保存しました', + 'dashboard.coverUploadError': 'アップロードに失敗しました', + 'dashboard.coverRemoveError': '削除に失敗しました', + 'dashboard.titleRequired': 'タイトルは必須です', + 'dashboard.endDateError': '終了日は開始日より後にしてください', + + // Settings + 'settings.title': '設定', + 'settings.subtitle': '個人設定を管理', + 'settings.tabs.display': '表示', + 'settings.tabs.map': '地図', + 'settings.tabs.notifications': '通知', + 'settings.tabs.integrations': '連携', + 'settings.tabs.account': 'アカウント', + 'settings.tabs.offline': 'オフライン', + 'settings.tabs.about': '情報', + 'settings.map': '地図', + 'settings.mapTemplate': '地図テンプレート', + 'settings.mapTemplatePlaceholder.select': 'テンプレートを選択…', + 'settings.mapDefaultHint': '空欄の場合は OpenStreetMap(既定)を使用', + 'settings.mapTemplatePlaceholder': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', + 'settings.mapHint': '地図タイルのURLテンプレート', + 'settings.mapProvider': '地図プロバイダー', + 'settings.mapProviderHint': '旅程プランナーと日記地図に影響します。Atlas は常に Leaflet を使用します。', + 'settings.mapLeafletSubtitle': 'クラシックな2D、任意のラスタータイル', + 'settings.mapMapboxSubtitle': 'ベクタータイル、3D建物・地形', + 'settings.mapExperimental': '実験的', + 'settings.mapMapboxToken': 'Mapbox アクセストークン', + 'settings.mapMapboxTokenHint': 'mapbox.com の公開トークン(pk.*)', + 'settings.mapMapboxTokenLink': 'mapbox.com → Access tokens', + 'settings.mapStyle': '地図スタイル', + 'settings.mapStylePlaceholder': 'Mapboxスタイルを選択', + 'settings.mapStyleHint': 'プリセットまたは mapbox://styles/USER/ID のURL', + 'settings.map3dBuildings': '3D建物・地形', + 'settings.map3dHint': 'ピッチ+実際の3D押し出し表示。衛星含む全スタイルで動作。', + 'settings.mapHighQuality': '高品質モード', + 'settings.mapHighQualityHint': 'アンチエイリアス+地球投影で、より鮮明でリアルに表示。', + 'settings.mapHighQualityWarning': '低性能デバイスではパフォーマンスに影響する場合があります。', + 'settings.mapTipLabel': 'ヒント:', + 'settings.mapTip': '右クリック+ドラッグで回転/傾き。中クリックで場所を追加(右クリックは回転用)。', + 'settings.latitude': '緯度', + 'settings.longitude': '経度', + 'settings.saveMap': '地図を保存', + 'settings.apiKeys': 'APIキー', + 'settings.mapsKey': 'Google Maps APIキー', + 'settings.mapsKeyHint': '場所検索用。Places API(新)が必要。console.cloud.google.com で取得', + 'settings.weatherKey': 'OpenWeatherMap APIキー', + 'settings.weatherKeyHint': '天気情報用。openweathermap.org/api で無料取得', + 'settings.keyPlaceholder': 'キーを入力…', + 'settings.configured': '設定済み', + 'settings.saveKeys': 'キーを保存', + 'settings.display': '表示', + 'settings.colorMode': 'カラーモード', + 'settings.light': 'ライト', + 'settings.dark': 'ダーク', + 'settings.auto': '自動', + 'settings.language': '言語', + 'settings.temperature': '温度単位', + 'settings.timeFormat': '時刻形式', + 'settings.routeCalculation': '経路計算', + 'settings.bookingLabels': '予約ルートのラベル', + 'settings.bookingLabelsHint': '地図に駅・空港名を表示。オフ時はアイコンのみ。', + 'settings.blurBookingCodes': '予約コードをぼかす', + 'settings.notifications': '通知', + 'settings.notifyTripInvite': '旅行の招待', + 'settings.notifyBookingChange': '予約の変更', + 'settings.notifyTripReminder': '旅行リマインダー', + 'settings.notifyTodoDue': 'ToDoの期限', + 'settings.notifyVacayInvite': 'Vacay fusion の招待', + 'settings.notifyPhotosShared': '共有写真(Immich)', + 'settings.notifyCollabMessage': 'チャットメッセージ(Collab)', + 'settings.notifyPackingTagged': '持ち物リスト:割り当て', + 'settings.notifyWebhook': 'Webhook通知', + 'settings.notifyVersionAvailable': '新しいバージョン', + 'settings.notificationPreferences.email': 'メール', + 'settings.notificationPreferences.webhook': 'Webhook', + 'settings.notificationPreferences.inapp': 'アプリ内', + 'settings.notificationPreferences.ntfy': 'Ntfy', + 'settings.notificationPreferences.noChannels': '通知チャネルが未設定です。管理者に設定を依頼してください。', + 'settings.webhookUrl.label': 'Webhook URL', + 'settings.webhookUrl.placeholder': 'https://discord.com/api/webhooks/...', + 'settings.webhookUrl.hint': 'Discord、Slack、または独自のWebhook URLを入力してください。', + 'settings.webhookUrl.saved': 'Webhook URLを保存しました', + 'settings.webhookUrl.test': 'テスト', + 'settings.webhookUrl.testSuccess': 'テストWebhookを送信しました', + 'settings.webhookUrl.testFailed': 'テストWebhookに失敗しました', + 'settings.ntfyUrl.topicLabel': 'Ntfy トピック', + 'settings.ntfyUrl.topicPlaceholder': 'my-trek-alerts', + 'settings.ntfyUrl.serverLabel': 'Ntfy サーバーURL(任意)', + 'settings.ntfyUrl.serverPlaceholder': 'https://ntfy.sh', + 'settings.ntfyUrl.hint': 'ntfyトピックを入力してください。サーバー未入力時は管理者設定の既定値を使用します。', + 'settings.ntfyUrl.tokenLabel': 'アクセストークン(任意)', + 'settings.ntfyUrl.tokenHint': 'パスワード保護トピックに必要です。', + 'settings.ntfyUrl.saved': 'Ntfy設定を保存しました', + 'settings.ntfyUrl.test': 'テスト', + 'settings.ntfyUrl.testSuccess': 'テスト通知を送信しました', + 'settings.ntfyUrl.testFailed': 'テスト通知に失敗しました', + 'settings.ntfyUrl.tokenCleared': 'アクセストークンを削除しました', + 'admin.notifications.title': '通知', + 'admin.notifications.hint': '通知チャネルを1つ選択してください。同時に有効にできるのは1つだけです。', + 'admin.notifications.none': '無効', + 'admin.notifications.email': 'メール(SMTP)', + 'admin.notifications.webhook': 'Webhook', + 'admin.notifications.ntfy': 'Ntfy', + 'admin.ntfy.hint': 'ユーザーが独自のntfyトピックを設定できるようにします。下で既定サーバーを設定してください。', + 'admin.notifications.save': '通知設定を保存', + 'admin.notifications.saved': '通知設定を保存しました', + 'admin.notifications.testWebhook': 'Webhookテスト送信', + 'admin.notifications.testWebhookSuccess': 'テストWebhookを送信しました', + 'admin.notifications.testWebhookFailed': 'テストWebhookに失敗しました', + 'admin.notifications.testNtfy': 'ntfyテスト送信', + 'admin.notifications.testNtfySuccess': 'テストntfyを送信しました', + 'admin.notifications.testNtfyFailed': 'テストntfyに失敗しました', + 'admin.notifications.emailPanel.title': 'メール(SMTP)', + 'admin.notifications.webhookPanel.title': 'Webhook', + 'admin.notifications.inappPanel.title': 'アプリ内', + 'admin.notifications.inappPanel.hint': 'アプリ内通知は常に有効で、全体では無効にできません。', + 'admin.notifications.adminWebhookPanel.title': '管理者Webhook', + 'admin.notifications.adminWebhookPanel.hint': '管理者通知専用のWebhookです(例:バージョン通知)。常に送信されます。', + 'admin.notifications.adminWebhookPanel.saved': '管理者Webhook URLを保存しました', + 'admin.notifications.adminWebhookPanel.testSuccess': 'テストWebhookを送信しました', + 'admin.notifications.adminWebhookPanel.testFailed': 'テストWebhookに失敗しました', + 'admin.notifications.adminWebhookPanel.alwaysOnHint': 'URLが設定されていると常に送信されます', + 'admin.notifications.adminNtfyPanel.title': '管理者Ntfy', + 'admin.notifications.adminNtfyPanel.hint': '管理者通知専用のntfyトピックです。', + 'admin.notifications.adminNtfyPanel.serverLabel': 'Ntfy サーバーURL', + 'admin.notifications.adminNtfyPanel.serverHint': 'ユーザー通知の既定サーバーとしても使用されます。', + 'admin.notifications.adminNtfyPanel.serverPlaceholder': 'https://ntfy.sh', + 'admin.notifications.adminNtfyPanel.topicLabel': '管理者トピック', + 'admin.notifications.adminNtfyPanel.topicPlaceholder': 'trek-admin-alerts', + 'admin.notifications.adminNtfyPanel.tokenLabel': 'アクセストークン(任意)', + 'admin.notifications.adminNtfyPanel.tokenCleared': '管理者アクセストークンを削除しました', + 'admin.notifications.adminNtfyPanel.saved': '管理者ntfy設定を保存しました', + 'admin.notifications.adminNtfyPanel.test': 'ntfyテスト送信', + 'admin.notifications.adminNtfyPanel.testSuccess': 'テストntfyを送信しました', + 'admin.notifications.adminNtfyPanel.testFailed': 'テストntfyに失敗しました', + 'admin.notifications.adminNtfyPanel.alwaysOnHint': 'トピック設定時は常に送信されます', + 'admin.notifications.adminNotificationsHint': '管理者専用通知の配信先を設定します。', + 'admin.notifications.tripReminders.title': '旅行リマインダー', + 'admin.notifications.tripReminders.hint': '旅行開始前に通知を送信します(旅行側の設定が必要)。', + 'admin.notifications.tripReminders.enabled': '旅行リマインダー有効', + 'admin.notifications.tripReminders.disabled': '旅行リマインダー無効', + 'admin.smtp.title': 'メール・通知', + 'admin.smtp.hint': 'メール通知送信用のSMTP設定。', + 'admin.smtp.testButton': 'テストメール送信', + 'admin.webhook.hint': 'ユーザーが独自のWebhook URLを設定できるようにします。', + 'admin.smtp.testSuccess': 'テストメールを送信しました', + 'admin.smtp.testFailed': 'テストメールに失敗しました', + 'settings.notificationsDisabled': '通知が未設定です。管理者に有効化を依頼してください。', + 'settings.notificationsActive': '有効なチャネル', + 'settings.notificationsManagedByAdmin': '通知イベントは管理者が設定します。', + 'dayplan.icsTooltip': 'カレンダーを書き出し(ICS)', + 'share.linkTitle': '公開リンク', + 'share.linkHint': 'ログイン不要で閲覧できるリンクを作成します(閲覧のみ)。', + 'share.createLink': 'リンク作成', + 'share.deleteLink': 'リンク削除', + 'share.createError': 'リンクを作成できませんでした', + 'common.copy': 'コピー', + 'common.copied': 'コピーしました', + 'share.permMap': '地図・プラン', + 'share.permBookings': '予約', + 'share.permPacking': '持ち物', + 'shared.expired': 'リンクが無効', + 'shared.expiredHint': 'この共有リンクは無効です。', + 'shared.readOnly': '読み取り専用', + 'shared.tabPlan': 'プラン', + 'shared.tabBookings': '予約', + 'shared.tabPacking': '持ち物', + 'shared.tabBudget': '予算', + 'shared.tabChat': 'チャット', + 'shared.days': '日', + 'shared.places': '場所', + 'shared.other': 'その他', + 'shared.totalBudget': '合計予算', + 'shared.messages': 'メッセージ', + 'shared.sharedVia': '共有元', + 'shared.confirmed': '確定', + 'shared.pending': '保留', + 'share.permBudget': '予算', + 'share.permCollab': 'チャット', + 'settings.on': 'オン', + 'settings.off': 'オフ', + 'settings.mcp.title': 'MCP設定', + 'settings.mcp.endpoint': 'MCPエンドポイント', + 'settings.mcp.clientConfig': 'クライアント設定', + 'settings.mcp.clientConfigHint': ' を下のAPIトークンに置き換えてください。', + 'settings.mcp.clientConfigHintOAuth': ' をOAuth 2.1の認証情報に置き換えてください。', + 'settings.mcp.copy': 'コピー', + 'settings.mcp.copied': 'コピーしました!', + 'settings.mcp.apiTokens': 'APIトークン', + 'settings.mcp.createToken': '新しいトークン', + 'settings.mcp.noTokens': 'トークンがありません。作成してください。', + 'settings.mcp.tokenCreatedAt': '作成日', + 'settings.mcp.tokenUsedAt': '最終使用', + 'settings.mcp.deleteTokenTitle': 'トークン削除', + 'settings.mcp.deleteTokenMessage': 'このトークンは即時無効になります。', + 'settings.mcp.modal.createTitle': 'APIトークン作成', + 'settings.mcp.modal.tokenName': 'トークン名', + 'settings.mcp.modal.tokenNamePlaceholder': '例:Claude Desktop', + 'settings.mcp.modal.creating': '作成中…', + 'settings.mcp.modal.create': '作成', + 'settings.mcp.modal.createdTitle': 'トークン作成完了', + 'settings.mcp.modal.createdWarning': '表示は一度きりです。今すぐ保存してください。', + 'settings.mcp.modal.done': '完了', + 'settings.mcp.toast.created': 'トークンを作成しました', + 'settings.mcp.toast.createError': 'トークン作成に失敗しました', + 'settings.mcp.toast.deleted': 'トークンを削除しました', + 'settings.mcp.toast.deleteError': 'トークン削除に失敗しました', + 'settings.mcp.apiTokensDeprecated': 'APIトークンは非推奨です。OAuth 2.1 クライアントを使用してください。', + 'settings.oauth.clients': 'OAuth 2.1 クライアント', + 'settings.oauth.clientsHint': '第三者アプリが接続できるよう登録します。', + 'settings.oauth.createClient': '新規クライアント', + 'settings.oauth.noClients': '登録されたクライアントはありません。', + 'settings.oauth.clientId': 'クライアントID', + 'settings.oauth.clientSecret': 'クライアントシークレット', + 'settings.oauth.deleteClient': 'クライアント削除', + 'settings.oauth.deleteClientMessage': 'このクライアントは完全に削除されます。', + 'settings.oauth.rotateSecret': 'シークレット更新', + 'settings.oauth.rotateSecretMessage': '新しいシークレットを生成します。', + 'settings.oauth.rotateSecretConfirm': '更新', + 'settings.oauth.rotateSecretConfirming': '更新中…', + 'settings.oauth.rotateSecretDoneTitle': '新しいシークレット', + 'settings.oauth.rotateSecretDoneWarning': '表示は一度きりです。今すぐ保存してください。', + 'settings.oauth.activeSessions': '有効なセッション', + 'settings.oauth.sessionScopes': 'スコープ', + 'settings.oauth.sessionExpires': '有効期限', + 'settings.oauth.revoke': '取り消し', + 'settings.oauth.revokeSession': 'セッション取り消し', + 'settings.oauth.revokeSessionMessage': 'このセッションのアクセスを即時無効にします。', + 'settings.oauth.modal.createTitle': 'OAuthクライアント登録', + 'settings.oauth.modal.presets': '簡単設定', + 'settings.oauth.modal.clientName': 'アプリ名', + 'settings.oauth.modal.clientNamePlaceholder': '例:Claude Web', + 'settings.oauth.modal.redirectUris': 'リダイレクトURI', + 'settings.oauth.modal.redirectUrisPlaceholder': 'https://your-app.com/callback', + 'settings.oauth.modal.redirectUrisHint': '1行につき1つ。HTTPS必須。', + 'settings.oauth.modal.scopes': '許可スコープ', + 'settings.oauth.modal.scopesHint': 'list_trips と get_trip_summary は常に利用可能です。', + 'settings.oauth.modal.selectAll': 'すべて選択', + 'settings.oauth.modal.deselectAll': 'すべて解除', + 'settings.oauth.modal.creating': '登録中…', + 'settings.oauth.modal.create': '登録', + 'settings.oauth.modal.createdTitle': '登録完了', + 'settings.oauth.modal.createdWarning': 'シークレットは一度しか表示されません。', + 'settings.oauth.toast.createError': '登録に失敗しました', + 'settings.oauth.toast.deleted': 'クライアントを削除しました', + 'settings.oauth.toast.deleteError': '削除に失敗しました', + 'settings.oauth.toast.revoked': 'セッションを取り消しました', + 'settings.oauth.toast.revokeError': '取り消しに失敗しました', + 'settings.oauth.toast.rotateError': '更新に失敗しました', + 'settings.account': 'アカウント', + 'settings.about': '情報', + 'settings.about.reportBug': '不具合報告', + 'settings.about.reportBugHint': '問題を見つけたらお知らせください', + 'settings.about.featureRequest': '機能リクエスト', + 'settings.about.featureRequestHint': '新機能を提案', + 'settings.about.wikiHint': 'ドキュメント・ガイド', + 'settings.about.supporters.badge': '月額サポーター', + 'settings.about.supporters.title': 'TREKの旅仲間', + 'settings.about.supporters.subtitle': '皆さんの支援がTREKの未来を支えています。', + 'settings.about.supporters.since': '{date}からサポート', + 'settings.about.supporters.tierEmpty': '最初の一人に', + 'settings.about.supporter.tier.noReturnTicket': '片道切符', + 'settings.about.supporter.tier.lostLuggageVip': 'ロストラゲージVIP', + 'settings.about.supporter.tier.businessClassDreamer': 'ビジネスクラスの夢', + 'settings.about.supporter.tier.budgetTraveller': '節約トラベラー', + 'settings.about.supporter.tier.hostelBunkmate': 'ホステル仲間', + 'settings.about.description': 'TREKはセルフホスト型の旅行プランナーです。', + 'settings.about.madeWith': 'Made with', + 'settings.about.madeBy': 'by Maurice とオープンソースコミュニティ。', + 'settings.username': 'ユーザー名', + 'settings.email': 'メール', + 'settings.role': '役割', + 'settings.roleAdmin': '管理者', + 'settings.oidcLinked': '連携先', + 'settings.changePassword': 'パスワード変更', + 'settings.currentPassword': '現在のパスワード', + 'settings.currentPasswordRequired': '現在のパスワードが必要です', + 'settings.newPassword': '新しいパスワード', + 'settings.confirmPassword': '新しいパスワード(確認)', + 'settings.updatePassword': 'パスワード更新', + 'settings.passwordRequired': '現在と新しいパスワードを入力してください', + 'settings.passwordTooShort': '8文字以上必要です', + 'settings.passwordMismatch': 'パスワードが一致しません', + 'settings.passwordWeak': '大文字・小文字・数字・記号を含めてください', + 'settings.passwordChanged': 'パスワードを変更しました', + 'settings.mustChangePassword': '続行するにはパスワード変更が必要です。', + 'settings.deleteAccount': 'アカウント削除', + 'settings.deleteAccountTitle': 'アカウントを削除しますか?', + 'settings.deleteAccountWarning': 'すべてのデータが完全に削除されます。', + 'settings.deleteAccountConfirm': '完全に削除', + 'settings.deleteBlockedTitle': '削除できません', + 'settings.deleteBlockedMessage': '唯一の管理者です。別のユーザーを管理者にしてください。', + 'settings.roleUser': 'ユーザー', + 'settings.saveProfile': 'プロフィールを保存', + 'settings.toast.mapSaved': '地図設定を保存しました', + 'settings.toast.keysSaved': 'APIキーを保存しました', + 'settings.toast.displaySaved': '表示設定を保存しました', + 'settings.toast.profileSaved': 'プロフィールを保存しました', + 'settings.uploadAvatar': 'プロフィール画像をアップロード', + 'settings.removeAvatar': 'プロフィール画像を削除', + 'settings.avatarUploaded': 'プロフィール画像を更新しました', + 'settings.avatarRemoved': 'プロフィール画像を削除しました', + 'settings.avatarError': 'アップロードに失敗しました', + 'settings.mfa.title': '二要素認証(2FA)', + 'settings.mfa.description': 'サインイン時に追加の認証を行います。', + 'settings.mfa.requiredByPolicy': '管理者により2FAが必須です。', + 'settings.mfa.backupTitle': 'バックアップコード', + 'settings.mfa.backupDescription': '認証アプリが使えない場合に使用します。', + 'settings.mfa.backupWarning': '今すぐ保存してください。各コードは1回限りです。', + 'settings.mfa.backupCopy': 'コードをコピー', + 'settings.mfa.backupDownload': 'TXTでダウンロード', + 'settings.mfa.backupPrint': '印刷 / PDF', + 'settings.mfa.backupCopied': 'バックアップコードをコピーしました', + 'settings.mfa.enabled': '2FAは有効です。', + 'settings.mfa.disabled': '2FAは無効です。', + 'settings.mfa.setup': '認証アプリを設定', + 'settings.mfa.scanQr': 'QRコードをスキャンするか、手動で入力してください。', + 'settings.mfa.secretLabel': 'シークレットキー(手動入力)', + 'settings.mfa.codePlaceholder': '6桁コード', + 'settings.mfa.enable': '2FAを有効化', + 'settings.mfa.cancelSetup': 'キャンセル', + 'settings.mfa.disableTitle': '2FAを無効化', + 'settings.mfa.disableHint': 'パスワードと現在のコードを入力してください。', + 'settings.mfa.disable': '2FAを無効化', + 'settings.mfa.toastEnabled': '2FAを有効にしました', + 'settings.mfa.toastDisabled': '2FAを無効にしました', + 'settings.mfa.demoBlocked': 'デモモードでは利用できません', + + // Login + 'login.error': 'ログインに失敗しました。認証情報を確認してください。', + 'login.tagline': 'あなたの旅行。\nあなたの計画。', + 'login.description': 'インタラクティブなマップ、予算、リアルタイム同期で、みんなで旅行を計画。', + 'login.features.maps': 'インタラクティブマップ', + 'login.features.mapsDesc': 'Google Places、経路、クラスタリング', + 'login.features.realtime': 'リアルタイム同期', + 'login.features.realtimeDesc': 'WebSocketで共同計画', + 'login.features.budget': '予算管理', + 'login.features.budgetDesc': 'カテゴリ、グラフ、人数別費用', + 'login.features.collab': 'コラボレーション', + 'login.features.collabDesc': '複数ユーザーで旅行を共有', + 'login.features.packing': '持ち物リスト', + 'login.features.packingDesc': 'カテゴリ、進捗、提案', + 'login.features.bookings': '予約', + 'login.features.bookingsDesc': '航空券、ホテル、レストランなど', + 'login.features.files': 'ドキュメント', + 'login.features.filesDesc': '書類のアップロードと管理', + 'login.features.routes': 'スマート経路', + 'login.features.routesDesc': '自動最適化&Google Maps書き出し', + 'login.selfHosted': 'セルフホスト · オープンソース · データはあなたのもの', + 'login.title': 'サインイン', + 'login.subtitle': 'おかえりなさい', + 'login.signingIn': 'サインイン中…', + 'login.signIn': 'サインイン', + 'login.createAdmin': '管理者アカウントを作成', + 'login.createAdminHint': 'TREKの最初の管理者アカウントを設定します。', + 'login.setNewPassword': '新しいパスワードを設定', + 'login.setNewPasswordHint': '続行する前にパスワードを変更してください。', + 'login.createAccount': 'アカウントを作成', + 'login.createAccountHint': '新しいアカウントを登録。', + 'login.creating': '作成中…', + 'login.noAccount': 'アカウントをお持ちでないですか?', + 'login.hasAccount': 'すでにアカウントをお持ちですか?', + 'login.register': '登録', + 'login.emailPlaceholder': 'your@email.com', + 'login.username': 'ユーザー名', + 'login.oidc.registrationDisabled': '登録は無効です。管理者に連絡してください。', + 'login.oidc.noEmail': 'プロバイダーからメールが取得できませんでした。', + 'login.oidc.tokenFailed': '認証に失敗しました。', + 'login.oidc.invalidState': 'セッションが無効です。もう一度お試しください。', + 'login.demoFailed': 'デモログインに失敗しました', + 'login.oidcSignIn': '{name}でサインイン', + 'login.oidcOnly': 'パスワード認証は無効です。SSOプロバイダーでサインインしてください。', + 'login.oidcLoggedOut': 'ログアウトしました。SSOプロバイダーで再度サインインしてください。', + 'login.demoHint': 'デモを試す — 登録不要', + 'login.mfaTitle': '二要素認証', + 'login.mfaSubtitle': '認証アプリの6桁コードを入力してください。', + 'login.mfaCodeLabel': '確認コード', + 'login.mfaCodeRequired': '認証アプリのコードを入力してください。', + 'login.mfaHint': 'Google Authenticator、Authy などのTOTPアプリを開いてください。', + 'login.mfaBack': '← サインインに戻る', + 'login.mfaVerify': '確認', + 'login.invalidInviteLink': '無効または期限切れの招待リンクです', + 'login.oidcFailed': 'OIDCログインに失敗しました', + 'login.usernameRequired': 'ユーザー名を入力してください', + 'login.passwordMinLength': 'パスワードは8文字以上である必要があります', + 'login.forgotPassword': 'パスワードを忘れた場合', + 'login.forgotPasswordTitle': 'パスワードをリセット', + 'login.forgotPasswordBody': '登録時のメールアドレスを入力してください。アカウントが存在する場合、リセット用リンクを送信します。', + 'login.forgotPasswordSubmit': 'リセットリンクを送信', + 'login.forgotPasswordSentTitle': 'メールを確認してください', + 'login.forgotPasswordSentBody': '該当するアカウントがある場合、リセットリンクを送信しました。リンクの有効期限は60分です。', + 'login.forgotPasswordSmtpHintOff': '注意:管理者がSMTPを設定していないため、リセットリンクはメールではなくサーバーコンソールに出力されます。', + 'login.backToLogin': 'ログインに戻る', + 'login.newPassword': '新しいパスワード', + 'login.confirmPassword': '新しいパスワード(確認)', + 'login.passwordsDontMatch': 'パスワードが一致しません', + 'login.mfaCode': '2FAコード', + 'login.resetPasswordTitle': '新しいパスワードを設定', + 'login.resetPasswordBody': '以前使用していない強力なパスワードを設定してください(8文字以上)。', + 'login.resetPasswordMfaBody': '2FAコードまたはバックアップコードを入力してリセットを完了してください。', + 'login.resetPasswordSubmit': 'パスワードをリセット', + 'login.resetPasswordVerify': '確認してリセット', + 'login.resetPasswordSuccessTitle': 'パスワードを更新しました', + 'login.resetPasswordSuccessBody': '新しいパスワードでログインできます。', + 'login.resetPasswordInvalidLink': '無効なリセットリンク', + 'login.resetPasswordInvalidLinkBody': 'リンクが無効または破損しています。新しいリンクをリクエストしてください。', + 'login.resetPasswordFailed': 'リセットに失敗しました。リンクの有効期限が切れている可能性があります。', + + // Register + 'register.passwordMismatch': 'パスワードが一致しません', + 'register.passwordTooShort': 'パスワードは8文字以上必要です', + 'register.failed': '登録に失敗しました', + 'register.getStarted': '始める', + 'register.subtitle': 'アカウントを作成して、理想の旅行計画を始めましょう。', + 'register.feature1': '無制限の旅行プラン', + 'register.feature2': 'インタラクティブなマップ表示', + 'register.feature3': '場所とカテゴリを管理', + 'register.feature4': '予約を管理', + 'register.feature5': '持ち物リストを作成', + 'register.feature6': '写真・ファイルを保存', + 'register.createAccount': 'アカウントを作成', + 'register.startPlanning': '旅行計画を始める', + 'register.minChars': '最小6文字', + 'register.confirmPassword': 'パスワード確認', + 'register.repeatPassword': 'パスワードを再入力', + 'register.registering': '登録中...', + 'register.register': '登録', + 'register.hasAccount': 'すでにアカウントをお持ちですか?', + 'register.signIn': 'サインイン', + + // Admin + 'admin.title': '管理', + 'admin.subtitle': 'ユーザー管理とシステム設定', + 'admin.tabs.users': 'ユーザー', + 'admin.tabs.categories': 'カテゴリ', + 'admin.tabs.backup': 'バックアップ', + 'admin.tabs.notifications': '通知', + 'admin.tabs.audit': '監査', + 'admin.stats.users': 'ユーザー', + 'admin.stats.trips': '旅行', + 'admin.stats.places': '場所', + 'admin.stats.photos': '写真', + 'admin.stats.files': 'ファイル', + 'admin.table.user': 'ユーザー', + 'admin.table.email': 'メール', + 'admin.table.role': '権限', + 'admin.table.created': '作成日', + 'admin.table.lastLogin': '最終ログイン', + 'admin.table.actions': '操作', + 'admin.you': '(あなた)', + 'admin.editUser': 'ユーザーを編集', + 'admin.newPassword': '新しいパスワード', + 'admin.newPasswordHint': '空欄の場合は現在のパスワードを維持', + 'admin.deleteUser': 'ユーザー「{name}」を削除しますか?すべての旅行が完全に削除されます。', + 'admin.deleteUserTitle': 'ユーザー削除', + 'admin.newPasswordPlaceholder': '新しいパスワードを入力…', + 'admin.toast.loadError': '管理データの読み込みに失敗しました', + 'admin.toast.userUpdated': 'ユーザーを更新しました', + 'admin.toast.updateError': '更新に失敗しました', + 'admin.toast.userDeleted': 'ユーザーを削除しました', + 'admin.toast.deleteError': '削除に失敗しました', + 'admin.toast.cannotDeleteSelf': '自分のアカウントは削除できません', + 'admin.toast.userCreated': 'ユーザーを作成しました', + 'admin.toast.createError': 'ユーザー作成に失敗しました', + 'admin.toast.fieldsRequired': 'ユーザー名、メール、パスワードは必須です', + 'admin.createUser': 'ユーザーを作成', + 'admin.invite.title': '招待リンク', + 'admin.invite.subtitle': '使い切り登録リンクを作成', + 'admin.invite.create': 'リンク作成', + 'admin.invite.createAndCopy': '作成してコピー', + 'admin.invite.empty': '招待リンクがまだありません', + 'admin.invite.maxUses': '最大使用回数', + 'admin.invite.expiry': '有効期限', + 'admin.invite.uses': '使用済み', + 'admin.invite.expiresAt': '期限', + 'admin.invite.createdBy': '作成者', + 'admin.invite.active': '有効', + 'admin.invite.expired': '期限切れ', + 'admin.invite.usedUp': '使用済み', + 'admin.invite.copied': '招待リンクをコピーしました', + 'admin.invite.copyLink': 'リンクをコピー', + 'admin.invite.deleted': '招待リンクを削除しました', + 'admin.invite.createError': '招待リンクの作成に失敗しました', + 'admin.invite.deleteError': '招待リンクの削除に失敗しました', + 'admin.tabs.settings': '設定', + 'admin.allowRegistration': '登録を許可', + 'admin.allowRegistrationHint': '新規ユーザーの自己登録を許可します', + 'admin.authMethods': '認証方法', + 'admin.passwordLogin': 'パスワードログイン', + 'admin.passwordLoginHint': 'メールとパスワードでのログインを許可', + 'admin.passwordRegistration': 'パスワード登録', + 'admin.passwordRegistrationHint': 'メールとパスワードでの新規登録を許可', + 'admin.oidcLogin': 'SSOログイン', + 'admin.oidcLoginHint': 'SSOでのログインを許可', + 'admin.oidcRegistration': 'SSO自動登録', + 'admin.oidcRegistrationHint': '新しいSSOユーザーを自動作成', + 'admin.envOverrideHint': 'パスワードログイン設定は OIDC_ONLY 環境変数で制御されています。', + 'admin.lockoutWarning': '少なくとも1つのログイン方法を有効にしてください', + 'admin.requireMfa': '二要素認証(2FA)を必須にする', + 'admin.requireMfaHint': '2FA未設定のユーザーは、利用前に設定が必要です。', + 'admin.apiKeys': 'APIキー', + 'admin.apiKeysHint': '任意。写真や天気などの拡張データを有効化します。', + 'admin.mapsKey': 'Google Maps APIキー', + 'admin.mapsKeyHint': '場所検索に必要。console.cloud.google.com で取得', + 'admin.mapsKeyHintLong': 'APIキーなしではOpenStreetMapを使用します。Google APIキーがあれば写真、評価、営業時間も表示できます。', + 'admin.recommended': '推奨', + 'admin.weatherKey': 'OpenWeatherMap APIキー', + 'admin.weatherKeyHint': '天気データ用。openweathermap.org で無料', + 'admin.validateKey': 'テスト', + 'admin.keyValid': '接続済み', + 'admin.keyInvalid': '無効', + 'admin.keySaved': 'APIキーを保存しました', + 'admin.oidcTitle': 'シングルサインオン(OIDC)', + 'admin.oidcSubtitle': 'Google、Apple、Authentik、Keycloak などでログインを許可します。', + 'admin.oidcDisplayName': '表示名', + 'admin.oidcIssuer': 'Issuer URL', + 'admin.oidcIssuerHint': 'OpenID ConnectのIssuer URL(例:https://accounts.google.com)', + 'admin.oidcSaved': 'OIDC設定を保存しました', + 'admin.oidcOnlyMode': 'パスワード認証を無効化', + 'admin.oidcOnlyModeHint': '有効にするとSSOのみ使用可能になり、パスワードログインと登録は無効になります。', + + // File Types + 'admin.fileTypes': '許可するファイル形式', + 'admin.fileTypesHint': 'ユーザーがアップロードできるファイル形式を設定します。', + 'admin.fileTypesFormat': '拡張子をカンマ区切り(例:jpg,png,pdf,doc)。すべて許可する場合は *。', + 'admin.fileTypesSaved': 'ファイル形式の設定を保存しました', + + 'admin.placesPhotos.title': '場所の写真', + 'admin.placesPhotos.subtitle': 'Google Places APIから写真を取得します。APIクォータ節約のため無効にできます。Wikimediaの写真には影響しません。', + 'admin.placesAutocomplete.title': '場所のオートコンプリート', + 'admin.placesAutocomplete.subtitle': '検索候補にGoogle Places APIを使用します。APIクォータ節約のため無効にできます。', + 'admin.placesDetails.title': '場所の詳細', + 'admin.placesDetails.subtitle': 'Google Places APIから営業時間、評価、ウェブサイトなどの詳細情報を取得します。APIクォータ節約のため無効にできます。', +// Packing Templates & Bag Tracking + 'admin.bagTracking.title': 'バッグ管理', + 'admin.bagTracking.subtitle': '持ち物の重量とバッグ割り当てを有効化', + 'admin.collab.chat.title': 'チャット', + 'admin.collab.chat.subtitle': '旅行の共同作業用リアルタイムメッセージ', + 'admin.collab.notes.title': 'ノート', + 'admin.collab.notes.subtitle': '共有ノートとドキュメント', + 'admin.collab.polls.title': '投票', + 'admin.collab.polls.subtitle': 'グループ投票・アンケート', + 'admin.collab.whatsnext.title': '次にすること', + 'admin.collab.whatsnext.subtitle': 'アクティビティ提案と次のステップ', + 'admin.tabs.config': 'カスタマイズ', + 'admin.tabs.defaults': 'ユーザーのデフォルト', + 'admin.defaultSettings.title': '既定のユーザー設定', + 'admin.defaultSettings.description': 'インスタンス全体の既定値を設定します。設定を変更していないユーザーにはこれらの値が適用されます。各ユーザーの設定変更は常に優先されます。', + 'admin.defaultSettings.saved': '既定値を保存しました', + 'admin.defaultSettings.reset': '組み込みの既定値に戻す', + 'admin.defaultSettings.resetToBuiltIn': 'リセット', + 'admin.tabs.templates': '持ち物テンプレート', + 'admin.packingTemplates.title': '持ち物テンプレート', + 'admin.packingTemplates.subtitle': '旅行で使い回せる持ち物リストを作成', + 'admin.packingTemplates.create': '新規テンプレート', + 'admin.packingTemplates.namePlaceholder': 'テンプレート名(例:ビーチ旅行)', + 'admin.packingTemplates.empty': 'テンプレートはまだありません', + 'admin.packingTemplates.items': 'アイテム', + 'admin.packingTemplates.categories': 'カテゴリ', + 'admin.packingTemplates.itemName': 'アイテム名', + 'admin.packingTemplates.itemCategory': 'カテゴリ', + 'admin.packingTemplates.categoryName': 'カテゴリ名(例:衣類)', + 'admin.packingTemplates.addCategory': 'カテゴリを追加', + 'admin.packingTemplates.created': 'テンプレートを作成しました', + 'admin.packingTemplates.deleted': 'テンプレートを削除しました', + 'admin.packingTemplates.loadError': 'テンプレートの読み込みに失敗しました', + 'admin.packingTemplates.createError': 'テンプレートの作成に失敗しました', + 'admin.packingTemplates.deleteError': 'テンプレートの削除に失敗しました', + 'admin.packingTemplates.saveError': '保存に失敗しました', + +// Addons + 'admin.tabs.addons': 'アドオン', + 'admin.addons.title': 'アドオン', + 'admin.addons.subtitle': '機能を有効/無効にしてTREKをカスタマイズします。', + 'admin.addons.catalog.packing.name': 'リスト', + 'admin.addons.catalog.packing.description': '旅行用の持ち物リストとToDo', + 'admin.addons.catalog.budget.name': '予算', + 'admin.addons.catalog.budget.description': '支出の管理と予算計画', + 'admin.addons.catalog.documents.name': 'ドキュメント', + 'admin.addons.catalog.documents.description': '旅行書類の保存・管理', + 'admin.addons.catalog.vacay.name': 'Vacay', + 'admin.addons.catalog.vacay.description': 'カレンダー表示の個人休暇プランナー', + 'admin.addons.catalog.atlas.name': 'Atlas', + 'admin.addons.catalog.atlas.description': '訪問国と旅行統計の世界地図', + 'admin.addons.catalog.collab.name': 'Collab', + 'admin.addons.catalog.collab.description': 'リアルタイムのメモ、投票、チャット', + 'admin.addons.catalog.memories.name': '写真(Immich)', + 'admin.addons.catalog.memories.description': 'Immichで旅行写真を共有', + 'admin.addons.catalog.mcp.name': 'MCP', + 'admin.addons.catalog.mcp.description': 'AI連携のためのModel Context Protocol', + 'admin.addons.subtitleBefore': '機能を有効/無効にして ', + 'admin.addons.subtitleAfter': ' をカスタマイズします。', + 'admin.addons.enabled': '有効', + 'admin.addons.disabled': '無効', + 'admin.addons.type.trip': '旅行', + 'admin.addons.type.global': '全体', + 'admin.addons.type.integration': '連携', + 'admin.addons.tripHint': '各旅行内のタブとして利用可能', + 'admin.addons.globalHint': 'メインナビの独立セクションとして利用可能', + 'admin.addons.integrationHint': '専用ページのないバックエンド/API連携', + 'admin.addons.toast.updated': 'アドオンを更新しました', + 'admin.addons.toast.error': 'アドオンの更新に失敗しました', + 'admin.addons.noAddons': '利用可能なアドオンはありません', +// Weather info + 'admin.weather.title': '天気データ', + 'admin.weather.badge': '2026年3月24日以降', + 'admin.weather.description': 'TREKは天気データにOpen‑Meteoを使用しています。無料でオープンソース、APIキーは不要です。', + 'admin.weather.forecast': '16日間予報', + 'admin.weather.forecastDesc': '以前は5日(OpenWeatherMap)', + 'admin.weather.climate': '過去の気候データ', + 'admin.weather.climateDesc': '16日以降は過去85年の平均値', + 'admin.weather.requests': '1日10,000リクエスト', + 'admin.weather.requestsDesc': '無料、APIキー不要', + 'admin.weather.locationHint': '各日の座標付き最初の場所を基準にします。場所が未割り当ての場合は、場所一覧の任意の場所を参照します。', + + // GitHub + 'admin.tabs.mcpTokens': 'MCPトークン', + 'admin.mcpTokens.title': 'MCPトークン', + 'admin.mcpTokens.subtitle': 'すべてのユーザーのAPIトークンを管理', + 'admin.mcpTokens.sectionTitle': 'API トークン', + 'admin.mcpTokens.owner': '所有者', + 'admin.mcpTokens.tokenName': 'トークン名', + 'admin.mcpTokens.created': '作成日', + 'admin.mcpTokens.lastUsed': '最終使用', + 'admin.mcpTokens.never': '未使用', + 'admin.mcpTokens.empty': 'MCPトークンはまだ作成されていません', + 'admin.mcpTokens.deleteTitle': 'トークンを削除', + 'admin.mcpTokens.deleteMessage': 'このトークンは即座に失効します。ユーザーはこのトークン経由のMCPアクセスを失います。', + 'admin.mcpTokens.deleteSuccess': 'トークンを削除しました', + 'admin.mcpTokens.deleteError': 'トークンの削除に失敗しました', + 'admin.mcpTokens.loadError': 'トークンの読み込みに失敗しました', + 'admin.oauthSessions.sectionTitle': 'OAuthセッション', + 'admin.oauthSessions.clientName': 'クライアント', + 'admin.oauthSessions.owner': '所有者', + 'admin.oauthSessions.scopes': 'スコープ', + 'admin.oauthSessions.created': '作成日時', + 'admin.oauthSessions.empty': '有効なOAuthセッションはありません', + 'admin.oauthSessions.revokeTitle': 'セッションを無効化', + 'admin.oauthSessions.revokeMessage': 'このOAuthセッションは即時無効化され、クライアントはMCPへのアクセスを失います。', + 'admin.oauthSessions.revokeSuccess': 'セッションを無効化しました', + 'admin.oauthSessions.revokeError': 'セッションの無効化に失敗しました', + 'admin.oauthSessions.loadError': 'OAuthセッションの読み込みに失敗しました', + 'admin.tabs.github': 'GitHub', + + 'admin.audit.subtitle': 'セキュリティおよび管理イベント(バックアップ、ユーザー、MFA、設定)。', + 'admin.audit.empty': '監査ログはまだありません。', + 'admin.audit.refresh': '更新', + 'admin.audit.loadMore': 'さらに読み込む', + 'admin.audit.showing': '{count}件表示 · 全{total}件', + 'admin.audit.col.time': '時刻', + 'admin.audit.col.user': 'ユーザー', + 'admin.audit.col.action': '操作', + 'admin.audit.col.resource': '対象', + 'admin.audit.col.ip': 'IP', + 'admin.audit.col.details': '詳細', + 'admin.github.title': 'リリース履歴', + 'admin.github.subtitle': '{repo} の最新アップデート', + 'admin.github.latest': '最新', + 'admin.github.prerelease': 'プレリリース', + 'admin.github.showDetails': '詳細を表示', + 'admin.github.hideDetails': '詳細を非表示', + 'admin.github.loadMore': 'さらに読み込む', + 'admin.github.loading': '読み込み中...', + 'admin.github.error': 'リリースの読み込みに失敗しました', + 'admin.github.by': '作成者', + 'admin.github.support': 'TREKの開発を支援', + + 'admin.update.available': '更新があります', + 'admin.update.text': 'TREK {version} が利用可能です。現在は {current} を使用しています。', + 'admin.update.button': 'GitHubで見る', + 'admin.update.install': '更新をインストール', + 'admin.update.confirmTitle': '更新をインストールしますか?', + 'admin.update.confirmText': 'TREKを {current} から {version} に更新します。更新後、サーバーは自動的に再起動します。', + 'admin.update.dataInfo': 'すべてのデータ(旅行、ユーザー、APIキー、アップロード、Vacay、Atlas、予算)は保持されます。', + 'admin.update.warning': '再起動中、アプリは短時間利用できません。', + 'admin.update.confirm': '今すぐ更新', + 'admin.update.installing': '更新中…', + 'admin.update.success': '更新が完了しました!サーバーを再起動しています…', + 'admin.update.failed': '更新に失敗しました', + 'admin.update.backupHint': '更新前にバックアップを作成することをおすすめします。', + 'admin.update.backupLink': 'バックアップへ', + 'admin.update.howTo': '更新方法', + 'admin.update.dockerText': 'TREKはDockerで実行されています。{version} に更新するには、サーバーで次のコマンドを実行してください:', + 'admin.update.reloadHint': '数秒後にページを再読み込みしてください。', + +// Vacay addon + 'vacay.subtitle': '休暇日数の計画と管理', + 'vacay.settings': '設定', + 'vacay.year': '年', + 'vacay.addYear': '翌年を追加', + 'vacay.addPrevYear': '前年を追加', + 'vacay.removeYear': '年を削除', + 'vacay.removeYearConfirm': '{year}年を削除しますか?', + 'vacay.removeYearHint': 'この年の休暇データと会社休日はすべて完全に削除されます。', + 'vacay.remove': '削除', + 'vacay.persons': '人物', + 'vacay.noPersons': '人物が追加されていません', + 'vacay.addPerson': '人物を追加', + 'vacay.editPerson': '人物を編集', + 'vacay.removePerson': '人物を削除', + 'vacay.removePersonConfirm': '{name}を削除しますか?', + 'vacay.removePersonHint': 'この人物のすべての休暇データが完全に削除されます。', + 'vacay.personName': '名前', + 'vacay.personNamePlaceholder': '名前を入力', + 'vacay.color': '色', + 'vacay.add': '追加', + 'vacay.legend': '凡例', + 'vacay.publicHoliday': '祝日', + 'vacay.companyHoliday': '会社休日', + 'vacay.weekend': '週末', + 'vacay.modeVacation': '休暇', + 'vacay.modeCompany': '会社休日', + 'vacay.entitlement': '付与日数', + 'vacay.entitlementDays': '日', + 'vacay.used': '使用済み', + 'vacay.remaining': '残り', + 'vacay.carriedOver': '{year}年から繰越', + 'vacay.blockWeekends': '週末を除外', + 'vacay.blockWeekendsHint': '週末に休暇を登録できないようにします', + 'vacay.weekendDays': '週末', + 'vacay.mon': '月', + 'vacay.tue': '火', + 'vacay.wed': '水', + 'vacay.thu': '木', + 'vacay.fri': '金', + 'vacay.sat': '土', + 'vacay.sun': '日', + 'vacay.publicHolidays': '祝日', + 'vacay.publicHolidaysHint': 'カレンダーに祝日を表示', + 'vacay.selectCountry': '国を選択', + 'vacay.selectRegion': '地域を選択(任意)', + 'vacay.addCalendar': 'カレンダーを追加', + 'vacay.calendarLabel': 'ラベル(任意)', + 'vacay.calendarColor': '色', + 'vacay.noCalendars': '祝日カレンダーはまだありません', + 'vacay.companyHolidays': '会社休日', + 'vacay.companyHolidaysHint': '会社全体の休日を設定できます', + 'vacay.companyHolidaysNoDeduct': '会社休日は休暇日数に含まれません。', + 'vacay.weekStart': '週の開始', + 'vacay.weekStartHint': 'カレンダーの週を月曜始まりにするか日曜始まりにするかを選択します', + 'vacay.carryOver': '繰越', + 'vacay.carryOverHint': '残りの休暇日数を翌年に自動で繰り越します', + 'vacay.sharing': '共有', + 'vacay.sharingHint': '他のTREKユーザーと休暇計画を共有', + 'vacay.owner': '所有者', + 'vacay.shareEmailPlaceholder': 'TREKユーザーのメール', + 'vacay.shareSuccess': '計画を共有しました', + 'vacay.shareError': '共有できませんでした', + 'vacay.dissolve': '統合を解除', + 'vacay.dissolveHint': 'カレンダーを分離します。データは保持されます。', + 'vacay.dissolveAction': '解除', + 'vacay.dissolved': 'カレンダーを分離しました', + 'vacay.fusedWith': '統合相手', + 'vacay.you': 'あなた', + 'vacay.noData': 'データなし', + 'vacay.changeColor': '色を変更', + 'vacay.inviteUser': 'ユーザーを招待', + 'vacay.inviteHint': '別のTREKユーザーを招待して、休暇カレンダーを共有します。', + 'vacay.selectUser': 'ユーザーを選択', + 'vacay.sendInvite': '招待を送信', + 'vacay.inviteSent': '招待を送信しました', + 'vacay.inviteError': '招待を送信できませんでした', + 'vacay.pending': '保留中', + 'vacay.noUsersAvailable': '利用可能なユーザーがいません', + 'vacay.accept': '承認', + 'vacay.decline': '拒否', + 'vacay.acceptFusion': '承認して統合', + 'vacay.inviteTitle': '統合の招待', + 'vacay.inviteWantsToFuse': 'が休暇カレンダーの共有を希望しています。', + 'vacay.fuseInfo1': '双方が1つの共有カレンダーですべての休暇を確認できます。', + 'vacay.fuseInfo2': '双方が互いの予定を作成・編集できます。', + 'vacay.fuseInfo3': '双方が予定の削除や付与日数の変更を行えます。', + 'vacay.fuseInfo4': '祝日や会社休日などの設定は共有されます。', + 'vacay.fuseInfo5': '統合はいつでも解除できます。データは保持されます。', + 'nav.myTrips': 'マイ旅行', + + // Atlas addon + 'atlas.subtitle': '世界に広がるあなたの旅の足跡', + 'atlas.countries': '国', + 'atlas.trips': '旅行', + 'atlas.places': '場所', + 'atlas.unmark': '削除', + 'atlas.confirmMark': 'この国を訪問済みにしますか?', + 'atlas.confirmUnmark': 'この国を訪問済みリストから削除しますか?', + 'atlas.confirmUnmarkRegion': 'この地域を訪問済みリストから削除しますか?', + 'atlas.markVisited': '訪問済みにする', + 'atlas.markVisitedHint': 'この国を訪問済みリストに追加', + 'atlas.markRegionVisitedHint': 'この地域を訪問済みリストに追加', + 'atlas.addToBucket': '行きたいリストに追加', + 'atlas.addPoi': '場所を追加', + 'atlas.searchCountry': '国を検索...', + 'atlas.bucketNamePlaceholder': '名前(国・都市・場所など)', + 'atlas.month': '月', + 'atlas.year': '年', + 'atlas.addToBucketHint': '行きたい場所として保存', + 'atlas.bucketWhen': '訪問予定はいつですか?', + 'atlas.statsTab': '統計', + 'atlas.bucketTab': '行きたいリスト', + 'atlas.addBucket': '行きたいリストに追加', + 'atlas.bucketNotesPlaceholder': 'メモ(任意)', + 'atlas.bucketEmpty': '行きたいリストは空です', + 'atlas.bucketEmptyHint': '行ってみたい場所を追加しましょう', + 'atlas.days': '日', + 'atlas.visitedCountries': '訪問国', + 'atlas.cities': '都市', + 'atlas.noData': '旅行データがありません', + 'atlas.noDataHint': '旅行を作成して場所を追加すると、マップに表示されます', + 'atlas.lastTrip': '前回の旅行', + 'atlas.nextTrip': '次の旅行', + 'atlas.daysLeft': '残り日数', + 'atlas.streak': '連続', + 'atlas.years': '年', + 'atlas.yearInRow': '年連続', + 'atlas.yearsInRow': '年連続', + 'atlas.tripIn': '旅行', + 'atlas.tripsIn': '旅行', + 'atlas.since': '開始', + 'atlas.europe': 'ヨーロッパ', + 'atlas.asia': 'アジア', + 'atlas.northAmerica': '北アメリカ', + 'atlas.southAmerica': '南アメリカ', + 'atlas.africa': 'アフリカ', + 'atlas.oceania': 'オセアニア', + 'atlas.other': 'その他', + 'atlas.firstVisit': '最初の旅行', + 'atlas.lastVisitLabel': '最後の旅行', + 'atlas.tripSingular': '旅行', + 'atlas.tripPlural': '旅行', + 'atlas.placeVisited': '訪問した場所', + 'atlas.placesVisited': '訪問した場所', + +// Trip Planner + 'trip.tabs.plan': '計画', + 'trip.tabs.transports': '移動', + 'trip.tabs.reservations': '予約', + 'trip.tabs.reservationsShort': '予約', + 'trip.tabs.packing': '持ち物リスト', + 'trip.tabs.packingShort': '持ち物', + 'trip.tabs.lists': 'リスト', + 'trip.tabs.listsShort': 'リスト', + 'trip.tabs.budget': '予算', + 'trip.tabs.files': 'ファイル', + 'trip.loading': '旅行を読み込み中...', + 'trip.loadingPhotos': '場所の写真を読み込み中...', + 'trip.mobilePlan': '計画', + 'trip.mobilePlaces': '場所', + 'trip.toast.placeUpdated': '場所を更新しました', + 'trip.toast.placeAdded': '場所を追加しました', + 'trip.toast.placeDeleted': '場所を削除しました', + 'trip.toast.selectDay': 'まず日を選択してください', + 'trip.toast.assignedToDay': '場所を日に割り当てました', + 'trip.toast.reorderError': '並び替えに失敗しました', + 'trip.toast.reservationUpdated': '予約を更新しました', + 'trip.toast.reservationAdded': '予約を追加しました', + 'trip.toast.deleted': '削除しました', + 'trip.confirm.deletePlace': 'この場所を削除してもよろしいですか?', + 'trip.confirm.deletePlaces': '{count}件の場所を削除してもよろしいですか?', + 'trip.toast.placesDeleted': '{count}件の場所を削除しました', + +// Day Plan Sidebar + 'dayplan.emptyDay': 'この日の予定はありません', + 'dayplan.cannotReorderTransport': '時刻が固定された予約は並び替えできません', + 'dayplan.confirmRemoveTimeTitle': '時刻を削除しますか?', + 'dayplan.confirmRemoveTimeBody': 'この場所には固定時刻({time})があります。移動すると時刻が削除され、自由に並び替えできます。', + 'dayplan.confirmRemoveTimeAction': '時刻を削除して移動', + 'dayplan.cannotDropOnTimed': '時刻指定の項目の間には配置できません', + 'dayplan.cannotBreakChronology': '時刻指定の項目や予約の時系列が崩れます', + 'dayplan.addNote': 'メモを追加', + 'dayplan.expandAll': 'すべての日を展開', + 'dayplan.collapseAll': 'すべての日を折りたたむ', + 'dayplan.editNote': 'メモを編集', + 'dayplan.noteAdd': 'メモを追加', + 'dayplan.noteEdit': 'メモを編集', + 'dayplan.noteTitle': 'メモ', + 'dayplan.noteSubtitle': '日別メモ', + 'dayplan.totalCost': '合計費用', + 'dayplan.days': '日', + 'dayplan.dayN': '{n}日目', + 'dayplan.calculating': '計算中...', + 'dayplan.route': 'ルート', + 'dayplan.optimize': '最適化', + 'dayplan.optimized': 'ルートを最適化しました', + 'dayplan.routeError': 'ルートの計算に失敗しました', + 'dayplan.toast.needTwoPlaces': 'ルート最適化には2つ以上の場所が必要です', + 'dayplan.toast.routeOptimized': 'ルートを最適化しました', + 'dayplan.toast.noGeoPlaces': '座標付きの場所がありません', + 'dayplan.confirmed': '確定', + 'dayplan.pendingRes': '保留', + 'dayplan.pdf': 'PDF', + 'dayplan.pdfTooltip': '日別計画をPDFで書き出し', + 'dayplan.pdfError': 'PDFの書き出しに失敗しました', + + // Places Sidebar + 'places.addPlace': '場所/アクティビティを追加', + 'places.importFile': 'ファイルをインポート', + 'places.sidebarDrop': 'ドロップしてインポート', + 'places.importFileHint': 'Google My Maps、Google Earth、GPSトラッカーなどの .gpx、.kml、.kmz ファイルをインポートできます。', + 'places.importFileDropHere': 'クリックしてファイルを選択、またはここにドラッグ&ドロップ', + 'places.importFileDropActive': 'ドロップして選択', + 'places.importFileUnsupported': '対応していないファイル形式です。.gpx、.kml、.kmz を使用してください。', + 'places.importFileTooLarge': 'ファイルが大きすぎます。最大 {maxMb} MB までです。', + 'places.importFileError': 'インポートに失敗しました', + 'places.importAllSkipped': 'すべての場所は既に旅行に含まれています。', + 'places.gpxImported': 'GPXから {count} 件の場所をインポートしました', + 'places.gpxImportTypes': '何をインポートしますか?', + 'places.gpxImportWaypoints': 'ウェイポイント', + 'places.gpxImportRoutes': 'ルート', + 'places.gpxImportTracks': 'トラック(経路付き)', + 'places.gpxImportNoneSelected': '少なくとも1つ選択してください。', + 'places.kmlImportTypes': '何をインポートしますか?', + 'places.kmlImportPoints': 'ポイント(プレースマーク)', + 'places.kmlImportPaths': 'パス(ライン)', + 'places.kmlImportNoneSelected': '少なくとも1つ選択してください。', + 'places.selectionCount': '{count} 件選択中', + 'places.deleteSelected': '選択を削除', + 'places.kmlKmzImported': 'KMZ/KMLから {count} 件の場所をインポートしました', + 'places.urlResolved': 'URLから場所をインポートしました', + 'places.importList': 'リストをインポート', + 'places.kmlKmzSummaryValues': 'プレースマーク: {total} • 追加: {created} • スキップ: {skipped}', + 'places.importGoogleList': 'Google リスト', + 'places.importNaverList': 'Naver リスト', + 'places.googleListHint': '共有されたGoogleマップのリストリンクを貼り付けてください。', + 'places.googleListImported': '「{list}」から {count} 件の場所をインポートしました', + 'places.googleListError': 'Googleマップのリストをインポートできませんでした', + 'places.naverListHint': '共有されたNaverマップのリストリンクを貼り付けてください。', + 'places.naverListImported': '「{list}」から {count} 件の場所をインポートしました', + 'places.naverListError': 'Naverマップのリストをインポートできませんでした', + 'places.viewDetails': '詳細を見る', + 'places.assignToDay': 'どの日に追加しますか?', + 'places.all': 'すべて', + 'places.unplanned': '未計画', + 'places.filterTracks': 'トラック', + 'places.search': '場所を検索…', + 'places.allCategories': 'すべてのカテゴリ', + 'places.categoriesSelected': 'カテゴリ', + 'places.clearFilter': 'フィルター解除', + 'places.count': '{count} 件の場所', + 'places.countSingular': '1 件の場所', + 'places.allPlanned': 'すべての場所が計画済みです', + 'places.noneFound': '場所が見つかりません', + 'places.editPlace': '場所を編集', + 'places.formName': '名前', + 'places.formNamePlaceholder': '例:エッフェル塔', + 'places.formDescription': '説明', + 'places.formDescriptionPlaceholder': '短い説明…', + 'places.formAddress': '住所', + 'places.formAddressPlaceholder': '通り、都市、国', + 'places.formLat': '緯度(例:48.8566)', + 'places.formLng': '経度(例:2.3522)', + 'places.formCategory': 'カテゴリ', + 'places.noCategory': 'カテゴリなし', + 'places.categoryNamePlaceholder': 'カテゴリ名', + 'places.formTime': '時間', + 'places.startTime': '開始', + 'places.endTime': '終了', + 'places.endTimeBeforeStart': '終了時間が開始時間より前です', + 'places.timeCollision': '時間が重複しています:', + 'places.formWebsite': 'ウェブサイト', + 'places.formNotes': 'メモ', + 'places.formNotesPlaceholder': '個人的なメモ…', + 'places.formReservation': '予約', + 'places.reservationNotesPlaceholder': '予約メモ、確認番号など…', + 'places.mapsSearchPlaceholder': '場所を検索…', + 'places.mapsSearchError': '場所の検索に失敗しました。', + 'places.loadingDetails': '詳細を読み込み中…', + 'places.osmHint': 'OpenStreetMapで検索しています(写真・営業時間・評価なし)。設定でGoogle APIキーを追加すると詳細が表示されます。', + 'places.osmActive': 'OpenStreetMapで検索中(写真・評価・営業時間なし)。設定でGoogle APIキーを追加してください。', + 'places.categoryCreateError': 'カテゴリの作成に失敗しました', + 'places.nameRequired': '名前を入力してください', + 'places.saveError': '保存に失敗しました', +// Place Inspector + 'inspector.opened': '営業中', + 'inspector.closed': '営業時間外', + 'inspector.openingHours': '営業時間', + 'inspector.showHours': '営業時間を表示', + 'inspector.files': 'ファイル', + 'inspector.remove': '削除', + 'inspector.filesCount': '{count}件のファイル', + 'inspector.removeFromDay': 'この日から削除', + 'inspector.addToDay': '日に追加', + 'inspector.confirmedRes': '確定済み予約', + 'inspector.pendingRes': '保留中の予約', + 'inspector.google': 'Googleマップで開く', + 'inspector.website': 'Webサイトを開く', + 'inspector.addRes': '予約', + 'inspector.editRes': '予約を編集', + 'inspector.participants': '参加者', + 'inspector.trackStats': '統計を記録', + +// Reservations + 'reservations.title': '予約', + 'reservations.empty': '予約はまだありません', + 'reservations.emptyHint': '航空券、ホテルなどの予約を追加しましょう', + 'reservations.add': '予約を追加', + 'reservations.addManual': '手動予約', + 'reservations.placeHint': 'ヒント:予約は場所から直接作成すると、日別計画に紐づけやすくなります。', + 'reservations.confirmed': '確定', + 'reservations.pending': '保留', + 'reservations.summary': '確定 {confirmed}件、保留 {pending}件', + 'reservations.fromPlan': '計画から', + 'reservations.showFiles': 'ファイルを表示', + 'reservations.editTitle': '予約を編集', + 'reservations.status': 'ステータス', + 'reservations.datetime': '日時', + 'reservations.startTime': '開始時刻', + 'reservations.endTime': '終了時刻', + 'reservations.date': '日付', + 'reservations.time': '時間', + 'reservations.timeAlt': '時間(代替、例:19:30)', + 'reservations.notes': 'メモ', + 'reservations.notesPlaceholder': '追加のメモ...', + 'reservations.meta.airline': '航空会社', + 'reservations.meta.flightNumber': '便名', + 'reservations.meta.from': '出発地', + 'reservations.meta.to': '到着地', + 'reservations.needsReview': '要確認', + 'reservations.needsReviewHint': '空港を自動で特定できませんでした。場所を確認してください。', + 'reservations.searchLocation': '駅・港・住所を検索…', + 'airport.searchPlaceholder': '空港コードまたは都市名(例:FRA)', + 'map.connections': '接続', + 'map.showConnections': '予約ルートを表示', + 'map.hideConnections': '予約ルートを非表示', + 'reservations.meta.trainNumber': '列車番号', + 'reservations.meta.platform': 'ホーム', + 'reservations.meta.seat': '座席', + 'reservations.meta.checkIn': 'チェックイン', + 'reservations.meta.checkOut': 'チェックアウト', + 'reservations.meta.linkAccommodation': '宿泊先', + 'reservations.meta.checkInUntil': 'チェックイン期限', + 'reservations.meta.pickAccommodation': '宿泊先にリンク', + 'reservations.meta.noAccommodation': 'なし', + 'reservations.meta.hotelPlace': '宿泊先', + 'reservations.meta.pickHotel': '宿泊先を選択', + 'reservations.meta.fromDay': '開始', + 'reservations.meta.toDay': '終了', + 'reservations.meta.selectDay': '日を選択', + 'reservations.type.flight': '航空便', + 'reservations.type.hotel': '宿泊', + 'reservations.type.restaurant': 'レストラン', + 'reservations.type.train': '列車', + 'reservations.type.car': 'レンタカー', + 'reservations.type.cruise': 'クルーズ', + 'reservations.type.event': 'イベント', + 'reservations.type.tour': 'ツアー', + 'reservations.type.other': 'その他', + 'reservations.confirm.delete': '予約「{name}」を削除しますか?', + 'reservations.confirm.deleteTitle': '予約を削除しますか?', + 'reservations.confirm.deleteBody': '「{name}」は完全に削除されます。', + 'reservations.toast.updated': '予約を更新しました', + 'reservations.toast.removed': '予約を削除しました', + 'reservations.toast.fileUploaded': 'ファイルをアップロードしました', + 'reservations.toast.uploadError': 'アップロードに失敗しました', + 'reservations.newTitle': '新しい予約', + 'reservations.bookingType': '予約タイプ', + 'reservations.titleLabel': 'タイトル', + 'reservations.titlePlaceholder': '例:Lufthansa LH123、Hotel Adlon', + 'reservations.locationAddress': '場所/住所', + 'reservations.locationPlaceholder': '住所、空港、ホテル...', + 'reservations.confirmationCode': '予約コード', + 'reservations.confirmationPlaceholder': '例:ABC12345', + 'reservations.day': '日', + 'reservations.noDay': '日なし', + 'reservations.place': '場所', + 'reservations.noPlace': '場所なし', + 'reservations.pendingSave': '保存されます…', + 'reservations.uploading': 'アップロード中...', + 'reservations.attachFile': 'ファイルを添付', + 'reservations.linkExisting': '既存ファイルをリンク', + 'reservations.toast.saveError': '保存に失敗しました', + 'reservations.toast.updateError': '更新に失敗しました', + 'reservations.toast.deleteError': '削除に失敗しました', + 'reservations.confirm.remove': '「{name}」の予約を削除しますか?', + 'reservations.linkAssignment': '日への割り当てにリンク', + 'reservations.pickAssignment': '計画から割り当てを選択...', + 'reservations.noAssignment': 'リンクなし(単独)', + 'reservations.price': '価格', + 'reservations.budgetCategory': '予算カテゴリ', + 'reservations.budgetCategoryPlaceholder': '例:交通、宿泊', + 'reservations.budgetCategoryAuto': '自動(予約タイプから)', + 'reservations.budgetHint': '保存時に予算エントリが自動で作成されます。', + 'reservations.departureDate': '出発', + 'reservations.arrivalDate': '到着', + 'reservations.departureTime': '出発時刻', + 'reservations.arrivalTime': '到着時刻', + 'reservations.pickupDate': '受取', + 'reservations.returnDate': '返却', + 'reservations.pickupTime': '受取時刻', + 'reservations.returnTime': '返却時刻', + 'reservations.endDate': '終了日', + 'reservations.meta.departureTimezone': '出発TZ', + 'reservations.meta.arrivalTimezone': '到着TZ', + 'reservations.span.departure': '出発', + 'reservations.span.arrival': '到着', + 'reservations.span.inTransit': '移動中', + 'reservations.span.pickup': '受取', + 'reservations.span.return': '返却', + 'reservations.span.active': '有効', + 'reservations.span.start': '開始', + 'reservations.span.end': '終了', + 'reservations.span.ongoing': '進行中', + 'reservations.validation.endBeforeStart': '終了日時は開始日時より後である必要があります', + 'reservations.addBooking': '予約を追加', + + // Budget + 'budget.title': '予算', + 'budget.exportCsv': 'CSVを書き出し', + 'budget.emptyTitle': '予算はまだありません', + 'budget.emptyText': 'カテゴリと項目を作成して旅行予算を計画しましょう', + 'budget.emptyPlaceholder': 'カテゴリ名を入力...', + 'budget.createCategory': 'カテゴリを作成', + 'budget.category': 'カテゴリ', + 'budget.categoryName': 'カテゴリ名', + 'budget.table.name': '名前', + 'budget.table.total': '合計', + 'budget.table.persons': '人数', + 'budget.table.days': '日数', + 'budget.table.perPerson': '1人あたり', + 'budget.table.perDay': '1日あたり', + 'budget.table.perPersonDay': '人/日', + 'budget.table.note': 'メモ', + 'budget.table.date': '日付', + 'budget.newEntry': '新しい項目', + 'budget.defaultEntry': '新しい項目', + 'budget.defaultCategory': '新しいカテゴリ', + 'budget.total': '合計', + 'budget.totalBudget': '総予算', + 'budget.byCategory': 'カテゴリ別', + 'budget.editTooltip': 'クリックして編集', + 'budget.linkedToReservation': '予約に連携中 — 名前はそちらで編集してください', + 'budget.confirm.deleteCategory': '{count}件の項目があるカテゴリ「{name}」を削除しますか?', + 'budget.deleteCategory': 'カテゴリを削除', + 'budget.perPerson': '1人あたり', + 'budget.paid': '支払済み', + 'budget.open': '未精算', + 'budget.noMembers': 'メンバー未割り当て', + 'budget.settlement': '精算', + 'budget.settlementInfo': '予算項目のメンバーアイコンをクリックして緑にすると、支払い済みを示します。精算では、誰が誰にいくら支払うべきかを表示します。', + 'budget.netBalances': '差引残高', + +// Files + 'files.title': 'ファイル', + 'files.pageTitle': 'ファイル・ドキュメント', + 'files.subtitle': '{trip} のファイル {count} 件', + 'files.download': 'ダウンロード', + 'files.openError': 'ファイルを開けませんでした', + 'files.downloadPdf': 'PDFをダウンロード', + 'files.count': '{count}件のファイル', + 'files.countSingular': '1件のファイル', + 'files.uploaded': '{count}件アップロード', + 'files.uploadError': 'アップロードに失敗しました', + 'files.dropzone': 'ここにファイルをドロップ', + 'files.dropzoneHint': 'またはクリックして参照', + 'files.allowedTypes': '画像、PDF、DOC、DOCX、XLS、XLSX、TXT、CSV · 最大50MB', + 'files.uploading': 'アップロード中...', + 'files.filterAll': 'すべて', + 'files.filterPdf': 'PDF', + 'files.filterImages': '画像', + 'files.filterDocs': 'ドキュメント', + 'files.filterCollab': 'Collabメモ', + 'files.sourceCollab': 'Collabメモより', + 'files.empty': 'ファイルはまだありません', + 'files.emptyHint': 'ファイルをアップロードして旅行に添付しましょう', + 'files.openTab': '新しいタブで開く', + 'files.confirm.delete': 'このファイルを削除しますか?', + 'files.toast.deleted': 'ファイルを削除しました', + 'files.toast.deleteError': 'ファイルの削除に失敗しました', + 'files.sourcePlan': '日別計画', + 'files.sourceBooking': '予約', + 'files.attach': '添付', + 'files.pasteHint': 'クリップボードから画像を貼り付けることもできます(Ctrl+V)', + 'files.trash': 'ゴミ箱', + 'files.trashEmpty': 'ゴミ箱は空です', + 'files.emptyTrash': 'ゴミ箱を空にする', + 'files.restore': '復元', + 'files.star': 'スター', + 'files.unstar': 'スター解除', + 'files.assign': '割り当て', + 'files.assignTitle': 'ファイルを割り当て', + 'files.assignPlace': '場所', + 'files.assignBooking': '予約', + 'files.unassigned': '未割り当て', + 'files.unlink': 'リンクを解除', + 'files.toast.trashed': 'ゴミ箱に移動しました', + 'files.toast.restored': 'ファイルを復元しました', + 'files.toast.trashEmptied': 'ゴミ箱を空にしました', + 'files.toast.assigned': 'ファイルを割り当てました', + 'files.toast.assignError': '割り当てに失敗しました', + 'files.toast.restoreError': '復元に失敗しました', + 'files.confirm.permanentDelete': 'このファイルを完全に削除しますか?元に戻せません。', + 'files.confirm.emptyTrash': 'ゴミ箱内のファイルをすべて完全に削除しますか?元に戻せません。', + 'files.noteLabel': 'メモ', + 'files.notePlaceholder': 'メモを追加...', + +// Packing + 'packing.title': '持ち物リスト', + 'packing.empty': '持ち物リストは空です', + 'packing.import': 'インポート', + 'packing.importTitle': '持ち物リストをインポート', + 'packing.importHint': '1行につき1項目。形式:カテゴリ, 名前, 重量(g・任意), バッグ(任意), checked/unchecked(任意)', + 'packing.importPlaceholder': '衛生用品, 歯ブラシ\n衣類, Tシャツ, 200\n書類, パスポート, , 機内持ち込み\n電子機器, 充電器, 50, スーツケース, checked', + 'packing.importCsv': 'CSV/TXTを読み込む', + 'packing.importAction': '{count}件をインポート', + 'packing.importSuccess': '{count}件インポートしました', + 'packing.importError': 'インポートに失敗しました', + 'packing.importEmpty': 'インポートする項目がありません', + 'packing.progress': '{packed}/{total} 梱包済み({percent}%)', + 'packing.clearChecked': 'チェック済み{count}件を削除', + 'packing.clearCheckedShort': '{count}件を削除', + 'packing.suggestions': 'おすすめ', + 'packing.suggestionsTitle': 'おすすめを追加', + 'packing.allSuggested': 'おすすめはすべて追加済み', + 'packing.allPacked': 'すべて梱包済み!', + 'packing.addPlaceholder': '新しい項目を追加...', + 'packing.categoryPlaceholder': 'カテゴリ...', + 'packing.filterAll': 'すべて', + 'packing.filterOpen': '未完了', + 'packing.filterDone': '完了', + 'packing.emptyTitle': '持ち物リストは空です', + 'packing.emptyHint': '項目を追加するか、おすすめを使いましょう', + 'packing.emptyFiltered': 'このフィルターに一致する項目はありません', + 'packing.menuRename': '名前を変更', + 'packing.menuCheckAll': 'すべてチェック', + 'packing.menuUncheckAll': 'すべて解除', + 'packing.menuDeleteCat': 'カテゴリを削除', + 'packing.noMembers': '旅行メンバーがいません', + 'packing.addItem': '項目を追加', + 'packing.addItemPlaceholder': '項目名...', + 'packing.addCategory': 'カテゴリを追加', + 'packing.newCategoryPlaceholder': 'カテゴリ名(例:衣類)', + 'packing.applyTemplate': 'テンプレートを適用', + 'packing.template': 'テンプレート', + 'packing.templateApplied': 'テンプレートから{count}件追加しました', + 'packing.templateError': 'テンプレートの適用に失敗しました', + 'packing.saveAsTemplate': 'テンプレートとして保存', + 'packing.templateName': 'テンプレート名', + 'packing.templateSaved': '持ち物リストをテンプレートとして保存しました', + 'packing.bags': 'バッグ', + 'packing.noBag': '未割り当て', + 'packing.totalWeight': '総重量', + 'packing.bagName': 'バッグ名...', + 'packing.addBag': 'バッグを追加', + 'packing.changeCategory': 'カテゴリを変更', + 'packing.confirm.clearChecked': 'チェック済み{count}件を削除しますか?', + 'packing.confirm.deleteCat': '{count}件の項目があるカテゴリ「{name}」を削除しますか?', + 'packing.defaultCategory': 'その他', + 'packing.toast.saveError': '保存に失敗しました', + 'packing.toast.deleteError': '削除に失敗しました', + 'packing.toast.renameError': '名前の変更に失敗しました', + 'packing.toast.addError': '追加に失敗しました', + +// Packing suggestions + 'packing.suggestions.items': [ + { name: 'パスポート', category: '書類' }, + { name: '身分証明書', category: '書類' }, + { name: '海外旅行保険', category: '書類' }, + { name: '航空券', category: '書類' }, + { name: 'クレジットカード', category: '金融' }, + { name: '現金', category: '金融' }, + { name: 'ビザ', category: '書類' }, + { name: 'Tシャツ', category: '衣類' }, + { name: 'ズボン', category: '衣類' }, + { name: '下着', category: '衣類' }, + { name: '靴下', category: '衣類' }, + { name: '上着', category: '衣類' }, + { name: '寝間着', category: '衣類' }, + { name: '水着', category: '衣類' }, + { name: 'レインジャケット', category: '衣類' }, + { name: '歩きやすい靴', category: '衣類' }, + { name: '歯ブラシ', category: '洗面用具' }, + { name: '歯磨き粉', category: '洗面用具' }, + { name: 'シャンプー', category: '洗面用具' }, + { name: 'デオドラント', category: '洗面用具' }, + { name: '日焼け止め', category: '洗面用具' }, + { name: 'カミソリ', category: '洗面用具' }, + { name: '充電器', category: '電子機器' }, + { name: 'モバイルバッテリー', category: '電子機器' }, + { name: 'ヘッドホン', category: '電子機器' }, + { name: '変換プラグ', category: '電子機器' }, + { name: 'カメラ', category: '電子機器' }, + { name: '鎮痛薬', category: '健康' }, + { name: '絆創膏', category: '健康' }, + { name: '消毒液', category: '健康' }, + ], + + // Members / Sharing + 'members.shareTrip': '旅行を共有', + 'members.inviteUser': 'ユーザーを招待', + 'members.selectUser': 'ユーザーを選択…', + 'members.invite': '招待', + 'members.allHaveAccess': 'すでに全員がアクセスできます。', + 'members.access': 'アクセス', + 'members.person': '人', + 'members.persons': '人', + 'members.you': 'あなた', + 'members.owner': 'オーナー', + 'members.leaveTrip': '旅行を退出', + 'members.removeAccess': 'アクセスを削除', + 'members.confirmLeave': '旅行を退出しますか?アクセスできなくなります。', + 'members.confirmRemove': 'このユーザーのアクセスを削除しますか?', + 'members.loadError': 'メンバーの読み込みに失敗しました', + 'members.added': '追加しました', + 'members.addError': '追加に失敗しました', + 'members.removed': 'メンバーを削除しました', + 'members.removeError': '削除に失敗しました', + +// Categories (Admin) + 'categories.title': 'カテゴリ', + 'categories.subtitle': '場所のカテゴリを管理', + 'categories.new': '新しいカテゴリ', + 'categories.empty': 'カテゴリはまだありません', + 'categories.namePlaceholder': 'カテゴリ名', + 'categories.icon': 'アイコン', + 'categories.color': '色', + 'categories.customColor': 'カスタムカラーを選択', + 'categories.preview': 'プレビュー', + 'categories.defaultName': 'カテゴリ', + 'categories.update': '更新', + 'categories.create': '作成', + 'categories.confirm.delete': 'カテゴリを削除しますか?このカテゴリの場所は削除されません。', + 'categories.toast.loadError': 'カテゴリの読み込みに失敗しました', + 'categories.toast.nameRequired': '名前を入力してください', + 'categories.toast.updated': 'カテゴリを更新しました', + 'categories.toast.created': 'カテゴリを作成しました', + 'categories.toast.saveError': '保存に失敗しました', + 'categories.toast.deleted': 'カテゴリを削除しました', + 'categories.toast.deleteError': '削除に失敗しました', + +// Backup (Admin) + 'backup.title': 'データバックアップ', + 'backup.subtitle': 'データベースとアップロードされたすべてのファイル', + 'backup.refresh': '更新', + 'backup.upload': 'バックアップをアップロード', + 'backup.uploading': 'アップロード中…', + 'backup.create': 'バックアップを作成', + 'backup.creating': '作成中…', + 'backup.empty': 'バックアップはまだありません', + 'backup.createFirst': '最初のバックアップを作成', + 'backup.download': 'ダウンロード', + 'backup.restore': '復元', + 'backup.confirm.restore': 'バックアップ「{name}」を復元しますか?\n\n現在のすべてのデータはバックアップで置き換えられます。', + 'backup.confirm.uploadRestore': 'バックアップファイル「{name}」をアップロードして復元しますか?\n\n現在のすべてのデータは上書きされます。', + 'backup.confirm.delete': 'バックアップ「{name}」を削除しますか?', + 'backup.toast.loadError': 'バックアップの読み込みに失敗しました', + 'backup.toast.created': 'バックアップを作成しました', + 'backup.toast.createError': 'バックアップの作成に失敗しました', + 'backup.toast.restored': 'バックアップを復元しました。ページを再読み込みします…', + 'backup.toast.restoreError': '復元に失敗しました', + 'backup.toast.uploadError': 'アップロードに失敗しました', + 'backup.toast.deleted': 'バックアップを削除しました', + 'backup.toast.deleteError': '削除に失敗しました', + 'backup.toast.downloadError': 'ダウンロードに失敗しました', + 'backup.toast.settingsSaved': '自動バックアップ設定を保存しました', + 'backup.toast.settingsError': '設定の保存に失敗しました', + 'backup.auto.title': '自動バックアップ', + 'backup.auto.subtitle': 'スケジュールに基づいて自動実行', + 'backup.auto.enable': '自動バックアップを有効化', + 'backup.auto.enableHint': '選択したスケジュールで自動的に作成されます', + 'backup.auto.interval': '間隔', + 'backup.auto.hour': '実行時刻', + 'backup.auto.hourHint': 'サーバーのローカル時刻({format}形式)', + 'backup.auto.dayOfWeek': '曜日', + 'backup.auto.dayOfMonth': '月の日', + 'backup.auto.dayOfMonthHint': 'すべての月に対応するため1~28に制限されています', + 'backup.auto.scheduleSummary': 'スケジュール', + 'backup.auto.summaryDaily': '毎日 {hour}:00', + 'backup.auto.summaryWeekly': '毎週{day} {hour}:00', + 'backup.auto.summaryMonthly': '毎月{day}日 {hour}:00', + 'backup.auto.envLocked': 'Docker', + 'backup.auto.envLockedHint': '自動バックアップはDockerの環境変数で設定されています。変更するにはdocker-compose.ymlを更新し、コンテナを再起動してください。', + 'backup.auto.copyEnv': 'Docker環境変数をコピー', + 'backup.auto.envCopied': 'Docker環境変数をコピーしました', + 'backup.auto.keepLabel': '古いバックアップを削除', + 'backup.dow.sunday': '日', + 'backup.dow.monday': '月', + 'backup.dow.tuesday': '火', + 'backup.dow.wednesday': '水', + 'backup.dow.thursday': '木', + 'backup.dow.friday': '金', + 'backup.dow.saturday': '土', + 'backup.interval.hourly': '毎時間', + 'backup.interval.daily': '毎日', + 'backup.interval.weekly': '毎週', + 'backup.interval.monthly': '毎月', + 'backup.keep.1day': '1日', + 'backup.keep.3days': '3日', + 'backup.keep.7days': '7日', + 'backup.keep.14days': '14日', + 'backup.keep.30days': '30日', + 'backup.keep.forever': '無期限', + +// Photos + 'photos.title': '写真', + 'photos.subtitle': '{trip} の写真 {count} 枚', + 'photos.dropHere': 'ここに写真をドロップ…', + 'photos.dropHereActive': 'ここに写真をドロップ', + 'photos.captionForAll': 'キャプション(全体)', + 'photos.captionPlaceholder': '任意のキャプション…', + 'photos.addCaption': 'キャプションを追加…', + 'photos.allDays': 'すべての日', + 'photos.noPhotos': 'まだ写真はありません', + 'photos.uploadHint': '旅行の写真をアップロード', + 'photos.clickToSelect': 'またはクリックして選択', + 'photos.linkPlace': '場所を紐づけ', + 'photos.noPlace': '場所なし', + 'photos.uploadN': '{n} 枚の写真をアップロード', + 'photos.linkDay': '日を紐づけ', + 'photos.noDay': '日付なし', + 'photos.dayLabel': '{number}日目', + 'photos.photoSelected': '写真を選択しました', + 'photos.photosSelected': '写真を選択しました', + 'photos.fileTypeHint': 'JPG、PNG、WebP · 最大 10 MB · 最大 30 枚', + +// Backup restore modal + 'backup.restoreConfirmTitle': 'バックアップを復元しますか?', + 'backup.restoreWarning': '現在のすべてのデータ(旅行、場所、ユーザー、アップロード)はバックアップで完全に置き換えられます。この操作は元に戻せません。', + 'backup.restoreTip': 'ヒント:復元前に現在の状態をバックアップすることをおすすめします。', + 'backup.restoreConfirm': 'はい、復元します', + +// PDF + 'pdf.travelPlan': '旅行計画', + 'pdf.planned': '予定', + 'pdf.costLabel': '費用(EUR)', + 'pdf.preview': 'PDFプレビュー', + 'pdf.saveAsPdf': 'PDFとして保存', + + // Planner + 'planner.places': '場所', + 'planner.bookings': '予約', + 'planner.packingList': '持ち物リスト', + 'planner.documents': 'ドキュメント', + 'planner.dayPlan': '日別計画', + 'planner.reservations': '予約', + 'planner.minTwoPlaces': '座標付きの場所が少なくとも2つ必要です', + 'planner.noGeoPlaces': '座標付きの場所がありません', + 'planner.routeCalculated': 'ルートを計算しました', + 'planner.routeCalcFailed': 'ルートを計算できませんでした', + 'planner.routeError': 'ルート計算中にエラーが発生しました', + 'planner.icsExportFailed': 'ICSの書き出しに失敗しました', + 'planner.routeOptimized': 'ルートを最適化しました', + 'planner.reservationUpdated': '予約を更新しました', + 'planner.reservationAdded': '予約を追加しました', + 'planner.confirmDeleteReservation': '予約を削除しますか?', + 'planner.reservationDeleted': '予約を削除しました', + 'planner.days': '日', + 'planner.allPlaces': 'すべての場所', + 'planner.totalPlaces': '合計{n}件の場所', + 'planner.noDaysPlanned': '計画された日がありません', + 'planner.editTrip': '旅行を編集 →', + 'planner.placeOne': '1件の場所', + 'planner.placeN': '{n}件の場所', + 'planner.addNote': 'メモを追加', + 'planner.noEntries': 'この日の予定はありません', + 'planner.addPlace': '場所/アクティビティを追加', + 'planner.addPlaceShort': '+ 場所/アクティビティ', + 'planner.resPending': '予約保留 · ', + 'planner.resConfirmed': '予約確定 · ', + 'planner.notePlaceholder': 'メモ…', + 'planner.noteTimePlaceholder': '時刻(任意)', + 'planner.noteExamplePlaceholder': '例:中央駅から14:30発のS3、7番桟橋からフェリー、昼食休憩…', + 'planner.totalCost': '合計費用', + 'planner.searchPlaces': '場所を検索…', + 'planner.allCategories': 'すべてのカテゴリ', + 'planner.noPlacesFound': '場所が見つかりません', + 'planner.addFirstPlace': '最初の場所を追加', + 'planner.noReservations': '予約はありません', + 'planner.addFirstReservation': '最初の予約を追加', + 'planner.new': '新規', + 'planner.addToDay': '+ 日', + 'planner.calculating': '計算中…', + 'planner.route': 'ルート', + 'planner.optimize': '最適化', + 'planner.openGoogleMaps': 'Googleマップで開く', + 'planner.selectDayHint': '左の一覧から日を選択すると、日別計画が表示されます', + 'planner.noPlacesForDay': 'この日の場所はまだありません', + 'planner.addPlacesLink': '場所を追加 →', + 'planner.minTotal': '最短合計', + 'planner.noReservation': '予約なし', + 'planner.removeFromDay': 'この日から削除', + 'planner.addToThisDay': 'この日に追加', + 'planner.overview': '概要', + 'planner.noDays': '日がありません', + 'planner.editTripToAddDays': '旅行を編集して日を追加', + 'planner.dayCount': '{n}日間', + 'planner.clickToUnlock': 'クリックして解除', + 'planner.keepPosition': '最適化中も位置を保持', + 'planner.dayDetails': '日詳細', + 'planner.dayN': '{n}日目', + +// Dashboard Stats + 'stats.countries': '国', + 'stats.cities': '都市', + 'stats.trips': '旅行', + 'stats.places': '場所', + 'stats.worldProgress': '世界進捗', + 'stats.visited': '訪問済み', + 'stats.remaining': '未訪問', + 'stats.visitedCountries': '訪問国', + +// Day Detail Panel + 'day.precipProb': '降水確率', + 'day.precipitation': '降水量', + 'day.wind': '風', + 'day.sunrise': '日の出', + 'day.sunset': '日の入り', + 'day.hourlyForecast': '時間別予報', + 'day.climateHint': '過去の平均値 — 実際の予報はこの日付の16日前から表示されます。', + 'day.noWeather': '天気データがありません。座標付きの場所を追加してください。', + 'day.overview': '1日の概要', + 'day.accommodation': '宿泊先', + 'day.addAccommodation': '宿泊先を追加', + 'day.hotelDayRange': '適用日', + 'day.noPlacesForHotel': '先に旅行に場所を追加してください', + 'day.allDays': 'すべて', + 'day.checkIn': 'チェックイン', + 'day.checkInUntil': 'チェックイン期限', + 'day.checkOut': 'チェックアウト', + 'day.confirmation': '確認', + 'day.editAccommodation': '宿泊先を編集', + 'day.reservations': '予約', + +// Photos / Immich + 'memories.title': '写真', + 'memories.notConnected': '{provider_name} が接続されていません', + 'memories.notConnectedHint': '設定で {provider_name} インスタンスを接続すると、この旅行に写真を追加できます。', + 'memories.notConnectedMultipleHint': '設定で次の写真プロバイダーのいずれかを接続してください:{provider_names}', + 'memories.noDates': '写真を読み込むには旅行の日付を追加してください。', + 'memories.noPhotos': '写真が見つかりません', + 'memories.noPhotosHint': '{provider_name} にこの旅行期間の写真がありません。', + 'memories.photosFound': '枚の写真', + 'memories.fromOthers': '他のユーザーから', + 'memories.sharePhotos': '写真を共有', + 'memories.sharing': '共有', + 'memories.reviewTitle': '写真を確認', + 'memories.reviewHint': 'クリックして共有から除外できます。', + 'memories.shareCount': '{count}枚の写真を共有', + //------------------------- + //todo section + 'memories.providerUrl': 'サーバーURL', + 'memories.providerApiKey': 'APIキー', + 'memories.providerUsername': 'ユーザー名', + 'memories.providerPassword': 'パスワード', + 'memories.providerOTP': 'MFAコード(有効な場合)', + 'memories.skipSSLVerification': 'SSL証明書の検証をスキップ', + 'memories.immichAutoUpload': 'アップロード時に旅程の写真をImmichにミラー', + 'memories.providerUrlHintSynology': 'URLにPhotosアプリのパスを含めてください(例:https://nas:5001/photo)', + 'memories.testConnection': '接続をテスト', + 'memories.testFirst': '先に接続をテストしてください', + 'memories.connected': '接続済み', + 'memories.disconnected': '未接続', + 'memories.connectionSuccess': '{provider_name} に接続しました', + 'memories.connectionError': '{provider_name} に接続できませんでした', + 'memories.saved': '{provider_name} の設定を保存しました', + 'memories.providerDisconnectedBanner': '{provider_name} との接続が切れています。写真を見るには設定で再接続してください。', + 'memories.saveError': '{provider_name} の設定を保存できませんでした', + //------------------------ + 'memories.addPhotos': '写真を追加', + 'memories.linkAlbum': 'アルバムをリンク', + 'memories.selectAlbum': '{provider_name} のアルバムを選択', + 'memories.selectAlbumMultiple': 'アルバムを選択', + 'memories.noAlbums': 'アルバムが見つかりません', + 'memories.syncAlbum': 'アルバムを同期', + 'memories.unlinkAlbum': 'アルバムのリンクを解除', + 'memories.photos': '写真', + 'memories.selectPhotos': '{provider_name} から写真を選択', + 'memories.selectPhotosMultiple': '写真を選択', + 'memories.selectHint': '写真をタップして選択してください。', + 'memories.selected': '選択済み', + 'memories.addSelected': '{count} 枚の写真を追加', + 'memories.alreadyAdded': '追加済み', + 'memories.private': '非公開', + 'memories.stopSharing': '共有を停止', + 'memories.oldest': '古い順', + 'memories.newest': '新しい順', + 'memories.allLocations': 'すべての場所', + 'memories.tripDates': '旅行期間', + 'memories.allPhotos': 'すべての写真', + 'memories.confirmShareTitle': '旅行メンバーと共有しますか?', + 'memories.confirmShareHint': '{count} 枚の写真がこの旅行の全メンバーに表示されます。後から個別に非公開にできます。', + 'memories.confirmShareButton': '写真を共有', + 'memories.error.loadAlbums': 'アルバムの読み込みに失敗しました', + 'memories.error.linkAlbum': 'アルバムのリンクに失敗しました', + 'memories.error.unlinkAlbum': 'アルバムのリンク解除に失敗しました', + 'memories.error.syncAlbum': 'アルバムの同期に失敗しました', + 'memories.error.loadPhotos': '写真の読み込みに失敗しました', + 'memories.error.addPhotos': '写真の追加に失敗しました', + 'memories.error.removePhoto': '写真の削除に失敗しました', + 'memories.error.toggleSharing': '共有設定の更新に失敗しました', + 'memories.saveRouteNotConfigured': 'このプロバイダーでは保存先が設定されていません', + 'memories.testRouteNotConfigured': 'このプロバイダーではテスト用の保存先が設定されていません', + 'memories.fillRequiredFields': '必須項目をすべて入力してください', + + // Collab Addon + 'collab.tabs.chat': 'チャット', + 'collab.tabs.notes': 'ノート', + 'collab.tabs.polls': '投票', +'collab.whatsNext.title': '次にすること', + 'collab.whatsNext.today': '今日', + 'collab.whatsNext.tomorrow': '明日', + 'collab.whatsNext.empty': '予定されたアクティビティはありません', + 'collab.whatsNext.until': '〜', + 'collab.whatsNext.emptyHint': '時間が設定されたアクティビティがここに表示されます', + 'collab.chat.send': '送信', + 'collab.chat.placeholder': 'メッセージを入力…', + 'collab.chat.empty': '会話を始めましょう', + 'collab.chat.emptyHint': 'メッセージは旅行メンバー全員と共有されます', + 'collab.chat.emptyDesc': 'アイデアや計画、最新情報を共有しましょう', + 'collab.chat.today': '今日', + 'collab.chat.yesterday': '昨日', + 'collab.chat.deletedMessage': 'メッセージを削除しました', + 'collab.chat.reply': '返信', + 'collab.chat.loadMore': '以前のメッセージを読み込む', + 'collab.chat.justNow': 'たった今', + 'collab.chat.minutesAgo': '{n}分前', + 'collab.chat.hoursAgo': '{n}時間前', + 'collab.notes.title': 'ノート', + 'collab.notes.new': '新規ノート', + 'collab.notes.empty': 'まだノートがありません', + 'collab.notes.emptyHint': 'アイデアや計画を書き留めましょう', + 'collab.notes.all': 'すべて', + 'collab.notes.titlePlaceholder': 'ノートのタイトル', + 'collab.notes.contentPlaceholder': '内容を入力…', + 'collab.notes.categoryPlaceholder': 'カテゴリ', + 'collab.notes.newCategory': '新しいカテゴリ…', + 'collab.notes.category': 'カテゴリ', + 'collab.notes.noCategory': 'カテゴリなし', + 'collab.notes.color': '色', + 'collab.notes.save': '保存', + 'collab.notes.cancel': 'キャンセル', + 'collab.notes.edit': '編集', + 'collab.notes.delete': '削除', + 'collab.notes.pin': '固定', + 'collab.notes.unpin': '固定を解除', + 'collab.notes.daysAgo': '{n}日前', + 'collab.notes.categorySettings': 'カテゴリ管理', + 'collab.notes.create': '作成', + 'collab.notes.website': 'ウェブサイト', + 'collab.notes.websitePlaceholder': 'https://...', + 'collab.notes.attachFiles': 'ファイルを添付', + 'collab.notes.noCategoriesYet': 'カテゴリがまだありません', + 'collab.notes.emptyDesc': 'ノートを作成して始めましょう', + 'collab.polls.title': '投票', + 'collab.polls.new': '新しい投票', + 'collab.polls.empty': 'まだ投票がありません', + 'collab.polls.emptyHint': '質問してみんなで投票しましょう', + 'collab.polls.question': '質問', + 'collab.polls.questionPlaceholder': '何をしますか?', + 'collab.polls.addOption': '+ 選択肢を追加', + 'collab.polls.optionPlaceholder': '選択肢 {n}', + 'collab.polls.create': '投票を作成', + 'collab.polls.close': '閉じる', + 'collab.polls.closed': '終了', + 'collab.polls.votes': '{n}票', + 'collab.polls.vote': '{n}票', + 'collab.polls.multipleChoice': '複数選択', + 'collab.polls.multiChoice': '複数選択', + 'collab.polls.deadline': '締切', + 'collab.polls.option': '選択肢', + 'collab.polls.options': '選択肢', + 'collab.polls.delete': '削除', + 'collab.polls.closedSection': '終了', + + // Permissions + 'admin.tabs.permissions': '権限', + 'perm.title': '権限設定', + 'perm.subtitle': 'アプリ全体の操作権限を管理', + 'perm.saved': '権限設定を保存しました', + 'perm.resetDefaults': '既定に戻す', + 'perm.customized': 'カスタマイズ済み', + 'perm.level.admin': '管理者のみ', + 'perm.level.tripOwner': '旅行オーナー', + 'perm.level.tripMember': '旅行メンバー', + 'perm.level.everybody': '全員', + 'perm.cat.trip': '旅行管理', + 'perm.cat.members': 'メンバー管理', + 'perm.cat.files': 'ファイル', + 'perm.cat.content': 'コンテンツと予定', + 'perm.cat.extras': '予算・持ち物・コラボ', + 'perm.action.trip_create': '旅行を作成', + 'perm.action.trip_edit': '旅行詳細を編集', + 'perm.action.trip_delete': '旅行を削除', + 'perm.action.trip_archive': '旅行をアーカイブ/復元', + 'perm.action.trip_cover_upload': 'カバー画像をアップロード', + 'perm.action.member_manage': 'メンバーを追加/削除', + 'perm.action.file_upload': 'ファイルをアップロード', + 'perm.action.file_edit': 'ファイル情報を編集', + 'perm.action.file_delete': 'ファイルを削除', + 'perm.action.place_edit': '場所を追加/編集/削除', + 'perm.action.day_edit': '日・メモ・割り当てを編集', + 'perm.action.reservation_edit': '予約を管理', + 'perm.action.budget_edit': '予算を管理', + 'perm.action.packing_edit': '持ち物を管理', + 'perm.action.collab_edit': 'コラボ(メモ・投票・チャット)', + 'perm.action.share_manage': '共有リンクを管理', + 'perm.actionHint.trip_create': '新しい旅行を作成できる人', + 'perm.actionHint.trip_edit': '旅行名や日付などを変更できる人', + 'perm.actionHint.trip_delete': '旅行を完全に削除できる人', + 'perm.actionHint.trip_archive': '旅行をアーカイブできる人', + 'perm.actionHint.trip_cover_upload': 'カバー画像を変更できる人', + 'perm.actionHint.member_manage': 'メンバーを招待/削除できる人', + 'perm.actionHint.file_upload': 'ファイルをアップロードできる人', + 'perm.actionHint.file_edit': 'ファイル説明やリンクを編集できる人', + 'perm.actionHint.file_delete': 'ファイルをゴミ箱へ移動/完全削除できる人', + 'perm.actionHint.place_edit': '場所を追加・編集・削除できる人', + 'perm.actionHint.day_edit': '日やメモ、割り当てを編集できる人', + 'perm.actionHint.reservation_edit': '予約を作成・編集・削除できる人', + 'perm.actionHint.budget_edit': '予算項目を管理できる人', + 'perm.actionHint.packing_edit': '持ち物やバッグを管理できる人', + 'perm.actionHint.collab_edit': 'メモや投票、メッセージを作成できる人', + 'perm.actionHint.share_manage': '公開共有リンクを管理できる人', + + // Undo + 'undo.button': '元に戻す', + 'undo.tooltip': '元に戻す: {action}', + 'undo.assignPlace': '場所を日に割り当て', + 'undo.removeAssignment': '日の割り当てを解除', + 'undo.reorder': '場所を並び替え', + 'undo.optimize': 'ルートを最適化', + 'undo.deletePlace': '場所を削除', + 'undo.deletePlaces': '場所を削除', + 'undo.moveDay': '場所を別の日に移動', + 'undo.lock': '場所のロックを切り替え', + 'undo.importGpx': 'GPXをインポート', + 'undo.importKeyholeMarkup': 'KMZ/KMLをインポート', + 'undo.importGoogleList': 'Googleマップをインポート', + 'undo.importNaverList': 'Naverマップをインポート', + 'undo.addPlace': '場所を追加', + 'undo.done': '元に戻しました: {action}', + + // Notifications + 'notifications.title': '通知', + 'notifications.markAllRead': 'すべて既読', + 'notifications.deleteAll': 'すべて削除', + 'notifications.showAll': 'すべて表示', + 'notifications.empty': '通知はありません', + 'notifications.emptyDescription': 'すべて確認済みです!', + 'notifications.all': 'すべて', + 'notifications.unreadOnly': '未読', + 'notifications.markRead': '既読にする', + 'notifications.markUnread': '未読にする', + 'notifications.delete': '削除', + 'notifications.system': 'システム', + 'notifications.synologySessionCleared.title': 'Synology Photosが切断されました', + 'notifications.synologySessionCleared.text': 'サーバーまたはアカウントが変更されました。設定で接続を再テストしてください。', + + // Notification test keys (dev only) + 'notifications.versionAvailable.title': '更新があります', + 'notifications.versionAvailable.text': 'TREK {version} が利用可能です。', + 'notifications.versionAvailable.button': '詳細を見る', + 'notifications.test.title': '{actor} からのテスト通知', + 'notifications.test.text': 'これはテスト通知です。', + 'notifications.test.booleanTitle': '{actor} が承認を求めています', + 'notifications.test.booleanText': 'テスト用の承認通知です。', + 'notifications.test.accept': '承認', + 'notifications.test.decline': '却下', + 'notifications.test.navigateTitle': '確認してください', + 'notifications.test.navigateText': 'テスト用の遷移通知です。', + 'notifications.test.goThere': '移動', + 'notifications.test.adminTitle': '管理者通知', + 'notifications.test.adminText': '{actor} が管理者全員に通知を送りました。', + 'notifications.test.tripTitle': '{actor} が旅行に投稿しました', + 'notifications.test.tripText': '旅行「{trip}」のテスト通知です。', + + // Todo + 'todo.subtab.packing': '持ち物リスト', + 'todo.subtab.todo': 'ToDo', + 'todo.completed': '完了', + 'todo.filter.all': 'すべて', + 'todo.filter.open': '未完了', + 'todo.filter.done': '完了', + 'todo.uncategorized': '未分類', + 'todo.namePlaceholder': 'タスク名', + 'todo.descriptionPlaceholder': '説明(任意)', + 'todo.unassigned': '未割り当て', + 'todo.noCategory': 'カテゴリなし', + 'todo.hasDescription': '説明あり', + 'todo.addItem': '新しいタスクを追加...', + 'todo.sidebar.sortBy': '並び替え', + 'todo.priority': '優先度', + 'todo.newCategoryLabel': '新規', + 'budget.categoriesLabel': 'カテゴリ', + 'todo.newCategory': 'カテゴリ名', + 'todo.addCategory': 'カテゴリを追加', + 'todo.newItem': '新しいタスク', + 'todo.empty': 'タスクはまだありません。追加して始めましょう!', + 'todo.filter.my': '自分のタスク', + 'todo.filter.overdue': '期限切れ', + 'todo.sidebar.tasks': 'タスク', + 'todo.sidebar.categories': 'カテゴリ', + 'todo.detail.title': 'タスク', + 'todo.detail.description': '説明', + 'todo.detail.category': 'カテゴリ', + 'todo.detail.dueDate': '期限', + 'todo.detail.assignedTo': '担当者', + 'todo.detail.delete': '削除', + 'todo.detail.save': '変更を保存', + 'todo.sortByPrio': '優先度', + 'todo.detail.priority': '優先度', + 'todo.detail.noPriority': 'なし', + 'todo.detail.create': 'タスクを作成', + + // Notifications — dev test events + 'notif.test.title': '[テスト] 通知', + 'notif.test.simple.text': 'これはシンプルなテスト通知です。', + 'notif.test.boolean.text': 'このテスト通知を承認しますか?', + 'notif.test.navigate.text': '下をクリックしてダッシュボードに移動してください。', + + // Notifications + 'notif.trip_invite.title': '旅行への招待', + 'notif.trip_invite.text': '{actor}が「{trip}」に招待しました', + 'notif.booking_change.title': '予約が更新されました', + 'notif.booking_change.text': '{actor}が「{trip}」の予約を更新しました', + 'notif.trip_reminder.title': '旅行リマインド', + 'notif.trip_reminder.text': '旅行「{trip}」がまもなく始まります!', + 'notif.todo_due.title': 'ToDoの期限', + 'notif.todo_due.text': '「{trip}」の{todo}は{due}が期限です', + 'notif.vacay_invite.title': 'Vacay Fusionへの招待', + 'notif.vacay_invite.text': '{actor}から旅行プランの統合に招待されました', + 'notif.photos_shared.title': '写真が共有されました', + 'notif.photos_shared.text': '{actor}が「{trip}」で{count}枚の写真を共有しました', + 'notif.collab_message.title': '新しいメッセージ', + 'notif.collab_message.text': '{actor}が「{trip}」でメッセージを送りました', + 'notif.packing_tagged.title': '持ち物の割り当て', + 'notif.packing_tagged.text': '{actor}が「{trip}」の{category}をあなたに割り当てました', + 'notif.version_available.title': '新しいバージョンがあります', + 'notif.version_available.text': 'TREK {version}が利用可能です', + 'notif.action.view_trip': '旅行を見る', + 'notif.action.view_collab': 'メッセージを見る', + 'notif.action.view_packing': '持ち物を見る', + 'notif.action.view_photos': '写真を見る', + 'notif.action.view_vacay': 'Vacayを見る', + 'notif.action.view_admin': '管理画面へ', + 'notif.action.view': '表示', + 'notif.action.accept': '承認', + 'notif.action.decline': '拒否', + 'notif.generic.title': '通知', + 'notif.generic.text': '新しい通知があります', + 'notif.dev.unknown_event.title': '[DEV] 不明なイベント', + 'notif.dev.unknown_event.text': 'イベントタイプ「{event}」はEVENT_NOTIFICATION_CONFIGに登録されていません', + +// Journey addon + 'journey.search.placeholder': '日記を検索…', + 'journey.search.noResults': '「{query}」に一致する日記はありません', + 'journey.title': '日記', + 'journey.subtitle': '旅の記録をリアルタイムで残そう', + 'journey.new': '新しい日記', + 'journey.create': '作成', + 'journey.titlePlaceholder': 'どこへ行きますか?', + 'journey.empty': '日記はまだありません', + 'journey.emptyHint': '次の旅を記録してみましょう', + 'journey.deleted': '日記を削除しました', + 'journey.createError': '日記を作成できませんでした', + 'journey.deleteError': '日記を削除できませんでした', + 'journey.deleteConfirmTitle': '削除', + 'journey.deleteConfirmMessage': '「{title}」を削除しますか?元に戻せません。', + 'journey.deleteConfirmGeneric': '本当に削除しますか?', + 'journey.notFound': '日記が見つかりません', + 'journey.photos': '写真', + 'journey.timelineEmpty': 'まだ立ち寄りがありません', + 'journey.timelineEmptyHint': 'チェックインするか、日記を書いて始めましょう', + 'journey.status.draft': '下書き', + 'journey.status.active': '進行中', + 'journey.status.completed': '完了', + 'journey.status.upcoming': '予定', + 'journey.status.archived': 'アーカイブ', + 'journey.checkin.add': 'チェックイン', + 'journey.checkin.namePlaceholder': '場所名', + 'journey.checkin.notesPlaceholder': 'メモ(任意)', + 'journey.checkin.save': '保存', + 'journey.checkin.error': 'チェックインを保存できませんでした', + 'journey.entry.add': '日記', + 'journey.entry.edit': '編集', + 'journey.entry.titlePlaceholder': 'タイトル(任意)', + 'journey.entry.bodyPlaceholder': '今日は何がありましたか?', + 'journey.entry.save': '保存', + 'journey.entry.error': '日記を保存できませんでした', + 'journey.photo.add': '写真', + 'journey.photo.uploadError': 'アップロードに失敗しました', + 'journey.share.share': '共有', + 'journey.share.public': '公開', + 'journey.share.linkCopied': '公開リンクをコピーしました', + 'journey.share.disabled': '公開共有は無効です', + 'journey.editor.titlePlaceholder': 'この瞬間に名前をつけて…', + 'journey.editor.bodyPlaceholder': 'この日のストーリーを書いてみよう…', + 'journey.editor.placePlaceholder': '場所(任意)', + 'journey.editor.tagsPlaceholder': 'タグ:穴場、最高の食事、また行きたい…', + 'journey.visibility.private': '非公開', + 'journey.visibility.shared': '共有', + 'journey.visibility.public': '公開', + 'journey.emptyState.title': 'ここから物語が始まります', + 'journey.emptyState.subtitle': '場所にチェックインするか、最初の日記を書いてみましょう', + +// Journey Frontpage + 'journey.frontpage.subtitle': '旅を、忘れられない物語に', + 'journey.frontpage.createJourney': '日記を作成', + 'journey.frontpage.activeJourney': '進行中の日記', + 'journey.frontpage.allJourneys': 'すべての日記', + 'journey.frontpage.journeys': '日記', + 'journey.frontpage.createNew': '新しい日記を作成', + 'journey.frontpage.createNewSub': '旅を選んで、物語を書き、共有しよう', + 'journey.frontpage.live': 'ライブ', + 'journey.frontpage.synced': '同期済み', + 'journey.frontpage.continueWriting': '続けて書く', + 'journey.frontpage.updated': '{time}に更新', + 'journey.frontpage.suggestionLabel': '旅行が終了しました', + 'journey.frontpage.suggestionText': '{title}を日記にしよう', + 'journey.frontpage.dismiss': '閉じる', + 'journey.frontpage.journeyName': '日記名', + 'journey.frontpage.namePlaceholder': '例:東南アジア 2026', + 'journey.frontpage.selectTrips': '旅行を選択', + 'journey.frontpage.tripsSelected': '件選択', + 'journey.frontpage.trips': '旅行', + 'journey.frontpage.placesImported': '場所がインポートされます', + 'journey.frontpage.places': '場所', + + // Journey Detail + 'journey.detail.backToJourney': '日記に戻る', + 'journey.detail.syncedWithTrips': '旅行と同期済み', + 'journey.detail.addEntry': 'エントリーを追加', + 'journey.detail.newEntry': '新しいエントリー', + 'journey.detail.editEntry': 'エントリーを編集', + 'journey.detail.noEntries': 'エントリーはまだありません', + 'journey.detail.noEntriesHint': '旅行を追加して下書きエントリーを作成しましょう', + 'journey.detail.noPhotos': '写真はまだありません', + 'journey.detail.noPhotosHint': 'エントリーに写真を追加するか、Immich/Synologyライブラリを表示', + 'journey.detail.journeyTab': '日記', + 'journey.detail.journeyStats': '統計', + 'journey.detail.syncedTrips': '同期中の旅行', + 'journey.detail.noTripsLinked': 'リンクされた旅行はありません', + 'journey.detail.contributors': '参加者', + 'journey.detail.readMore': 'もっと見る', + 'journey.detail.prosCons': '良かった点・気になった点', + 'journey.detail.photos': '写真', + 'journey.detail.day': '{number}日目', + 'journey.detail.places': '場所', + +// Journey Detail — Stats + 'journey.stats.days': '日数', + 'journey.stats.cities': '都市', + 'journey.stats.entries': 'エントリー', + 'journey.stats.photos': '写真', + 'journey.stats.places': '場所', + 'journey.skeletons.show': '提案を表示', + 'journey.skeletons.hide': '提案を非表示', + +// Journey Detail — Verdict + 'journey.verdict.lovedIt': '最高だった', + 'journey.verdict.couldBeBetter': '改善の余地あり', + +// Journey Detail — Synced badge + 'journey.synced.places': '場所', + 'journey.synced.synced': '同期済み', + +// Journey Entry Editor + 'journey.editor.discardChangesConfirm': '未保存の変更があります。破棄しますか?', + 'journey.editor.uploadPhotos': '写真をアップロード', + 'journey.editor.uploading': 'アップロード中…', + 'journey.editor.fromGallery': 'ギャラリーから', + 'journey.editor.allPhotosAdded': 'すべての写真は追加済みです', + 'journey.editor.writeStory': 'ストーリーを書く…', + 'journey.editor.prosCons': '良かった点・気になった点', + 'journey.editor.pros': '良かった点', + 'journey.editor.cons': '気になった点', + 'journey.editor.proPlaceholder': '良かったこと…', + 'journey.editor.conPlaceholder': 'いまいちだったこと…', + 'journey.editor.addAnother': '追加', + 'journey.editor.date': '日付', + 'journey.editor.location': '場所', + 'journey.editor.searchLocation': '場所を検索…', + 'journey.editor.mood': '気分', + 'journey.editor.weather': '天気', + 'journey.editor.photoFirst': '1番目', + 'journey.editor.makeFirst': '1番目にする', + 'journey.editor.searching': '検索中…', + +// Journey Entry — Moods + 'journey.mood.amazing': '最高', + 'journey.mood.good': '良い', + 'journey.mood.neutral': '普通', + 'journey.mood.rough': '大変', + +// Journey Entry — Weather + 'journey.weather.sunny': '晴れ', + 'journey.weather.partly': '晴れ時々くもり', + 'journey.weather.cloudy': 'くもり', + 'journey.weather.rainy': '雨', + 'journey.weather.stormy': '嵐', + 'journey.weather.cold': '雪', + +// Journey — Trip Linking + 'journey.trips.linkTrip': '旅行をリンク', + 'journey.trips.searchTrip': '旅行を検索', + 'journey.trips.searchPlaceholder': '旅行名または目的地…', + 'journey.trips.noTripsAvailable': '利用できる旅行がありません', + 'journey.trips.link': 'リンク', + 'journey.trips.tripLinked': '旅行をリンクしました', + 'journey.trips.linkFailed': 'リンクに失敗しました', + 'journey.trips.addTrip': '旅行を追加', + 'journey.trips.unlinkTrip': 'リンク解除', + 'journey.trips.unlinkMessage': '「{title}」のリンクを解除しますか?この旅行から同期されたエントリーと写真はすべて完全に削除されます。元に戻せません。', + 'journey.trips.unlink': '解除', + 'journey.trips.tripUnlinked': 'リンクを解除しました', + 'journey.trips.unlinkFailed': '解除に失敗しました', + 'journey.trips.noTripsLinkedSettings': 'リンクされた旅行はありません', + +// Journey — Contributors + 'journey.contributors.invite': '参加者を招待', + 'journey.contributors.searchUser': 'ユーザーを検索', + 'journey.contributors.searchPlaceholder': 'ユーザー名またはメール…', + 'journey.contributors.noUsers': 'ユーザーが見つかりません', + 'journey.contributors.role': '役割', + 'journey.contributors.added': '参加者を追加しました', + 'journey.contributors.addFailed': '追加に失敗しました', + 'journey.contributors.remove': '参加者を削除', + 'journey.contributors.removeConfirm': '{username}をこの日記から削除しますか?', + 'journey.contributors.removed': '参加者を削除しました', + 'journey.contributors.removeFailed': '削除に失敗しました', + +// Journey — Share + 'journey.share.publicShare': '公開共有', + 'journey.share.createLink': '共有リンクを作成', + 'journey.share.linkCreated': '共有リンクを作成しました', + 'journey.share.createFailed': 'リンク作成に失敗しました', + 'journey.share.copy': 'コピー', + 'journey.share.copied': 'コピーしました!', + 'journey.share.timeline': 'タイムライン', + 'journey.share.gallery': 'ギャラリー', + 'journey.share.map': 'マップ', + 'journey.share.removeLink': '共有リンクを削除', + 'journey.share.linkDeleted': '共有リンクを削除しました', + 'journey.share.deleteFailed': '削除に失敗しました', + 'journey.share.updateFailed': '更新に失敗しました', + +// Journey — Invite + 'journey.invite.role': '役割', + 'journey.invite.viewer': '閲覧者', + 'journey.invite.editor': '編集者', + 'journey.invite.invite': '招待', + 'journey.invite.inviting': '招待中…', + +// Journey — Settings Dialog + 'journey.settings.title': '日記設定', + 'journey.settings.coverImage': 'カバー画像', + 'journey.settings.changeCover': 'カバーを変更', + 'journey.settings.addCover': 'カバー画像を追加', + 'journey.settings.name': '名前', + 'journey.settings.subtitle': 'サブタイトル', + 'journey.settings.subtitlePlaceholder': '例:タイ・ベトナム・カンボジア', + 'journey.settings.endJourney': '日記をアーカイブ', + 'journey.settings.reopenJourney': '日記を復元', + 'journey.settings.archived': '日記をアーカイブしました', + 'journey.settings.reopened': '日記を復元しました', + 'journey.settings.endDescription': 'Liveバッジを非表示にします。いつでも再開できます。', + 'journey.settings.delete': '削除', + 'journey.settings.deleteJourney': '日記を削除', + 'journey.settings.deleteMessage': '「{title}」を削除しますか?すべてのエントリーと写真が失われます。', + 'journey.settings.saved': '設定を保存しました', + 'journey.settings.saveFailed': '保存に失敗しました', + 'journey.settings.coverUpdated': 'カバーを更新しました', + 'journey.settings.coverFailed': 'アップロードに失敗しました', + 'journey.settings.failedToDelete': '削除に失敗しました', + 'journey.entries.deleteTitle': 'エントリーを削除', + 'journey.photosUploaded': '{count}枚の写真をアップロード', + 'journey.photosAdded': '{count}枚の写真を追加', + +// Journey — Public Page + 'journey.public.notFound': '見つかりません', + 'journey.public.notFoundMessage': 'この日記は存在しないか、リンクの有効期限が切れています。', + 'journey.public.readOnly': '閲覧のみ · 公開日記', + 'journey.public.tagline': '旅の記録&探索キット', + 'journey.public.sharedVia': '共有元', + 'journey.public.madeWith': '作成:', + +// Journey — PDF Export + 'journey.pdf.journeyBook': '日記ブック', + 'journey.pdf.madeWith': 'Made with TREK', + 'journey.pdf.day': '日目', + 'journey.pdf.theEnd': 'おわり', + 'journey.pdf.saveAsPdf': 'PDFとして保存', + 'journey.pdf.pages': 'ページ', + 'journey.picker.tripPeriod': '旅行期間', + 'journey.picker.dateRange': '日付範囲', + 'journey.picker.allPhotos': 'すべての写真', + 'journey.picker.albums': 'アルバム', + 'journey.picker.selected': '選択中', + 'journey.picker.addTo': '追加先', + 'journey.picker.newGallery': '新しいギャラリー', + 'journey.picker.selectAll': 'すべて選択', + 'journey.picker.deselectAll': '選択解除', + 'journey.picker.noAlbums': 'アルバムがありません', + 'journey.picker.selectDate': '日付を選択', + 'journey.picker.search': '検索', + +// Dashboard Mobile + 'dashboard.greeting.morning': 'おはようございます、', + 'dashboard.greeting.afternoon': 'こんにちは、', + 'dashboard.greeting.evening': 'こんばんは、', + 'dashboard.mobile.liveNow': 'ライブ中', + 'dashboard.mobile.tripProgress': '旅行の進行状況', + 'dashboard.mobile.daysLeft': '残り{count}日', + 'dashboard.mobile.places': '場所', + 'dashboard.mobile.buddies': '仲間', + 'dashboard.mobile.newTrip': '新しい旅行', + 'dashboard.mobile.currency': '通貨', + 'dashboard.mobile.timezone': 'タイムゾーン', + 'dashboard.mobile.upcomingTrips': '今後の旅行', + 'dashboard.mobile.yourTrips': 'あなたの旅行', + 'dashboard.mobile.trips': '旅行', + 'dashboard.mobile.starts': '開始', + 'dashboard.mobile.duration': '期間', + 'dashboard.mobile.day': '日', + 'dashboard.mobile.days': '日', + 'dashboard.mobile.ongoing': '進行中', + 'dashboard.mobile.startsToday': '今日開始', + 'dashboard.mobile.tomorrow': '明日', + 'dashboard.mobile.inDays': '{count}日後', + 'dashboard.mobile.inMonths': '{count}か月後', + 'dashboard.mobile.completed': '完了', + 'dashboard.mobile.currencyConverter': '通貨換算', + + // BottomNav & Profile + 'nav.profile': 'プロフィール', + 'nav.bottomSettings': '設定', + 'nav.bottomAdmin': '管理者設定', + 'nav.bottomLogout': 'ログアウト', + 'nav.bottomAdminBadge': '管理者', + +// DayPlan Mobile + 'dayplan.mobile.addPlace': '場所を追加', + 'dayplan.mobile.searchPlaces': '場所を検索…', + 'dayplan.mobile.allAssigned': 'すべて割り当て済み', + 'dayplan.mobile.noMatch': '一致なし', + 'dayplan.mobile.createNew': '新しい場所を作成', + +'admin.addons.catalog.journey.name': '日記', + 'admin.addons.catalog.journey.description': 'チェックイン、写真、日ごとのストーリーで旅を記録', + +// OAuth scope groups + 'oauth.scope.group.trips': '旅行', + 'oauth.scope.group.places': '場所', + 'oauth.scope.group.atlas': '地図', + 'oauth.scope.group.packing': '持ち物', + 'oauth.scope.group.todos': 'ToDo', + 'oauth.scope.group.budget': '予算', + 'oauth.scope.group.reservations': '予約', + 'oauth.scope.group.collab': 'コラボ', + 'oauth.scope.group.notifications': '通知', + 'oauth.scope.group.vacay': '休暇', + 'oauth.scope.group.geo': '地図', + 'oauth.scope.group.weather': '天気', + 'oauth.scope.group.journey': '日記', + +// OAuth scope labels & descriptions + 'oauth.scope.trips:read.label': '旅行・旅程を表示', + 'oauth.scope.trips:read.description': '旅行、日程、メモ、メンバーを閲覧', + 'oauth.scope.trips:write.label': '旅行・旅程を編集', + 'oauth.scope.trips:write.description': '旅行や日程、メモの作成・更新、メンバー管理', + 'oauth.scope.trips:delete.label': '旅行を削除', + 'oauth.scope.trips:delete.description': '旅行全体を完全に削除(元に戻せません)', + 'oauth.scope.trips:share.label': '共有リンクを管理', + 'oauth.scope.trips:share.description': '旅行の公開共有リンクを作成・更新・無効化', + 'oauth.scope.places:read.label': '場所・地図データを表示', + 'oauth.scope.places:read.description': '場所、日への割り当て、タグ、カテゴリを閲覧', + 'oauth.scope.places:write.label': '場所を管理', + 'oauth.scope.places:write.description': '場所、割り当て、タグの作成・更新・削除', + 'oauth.scope.atlas:read.label': '地図を表示', + 'oauth.scope.atlas:read.description': '訪問した国・地域、バケットリストを閲覧', + 'oauth.scope.atlas:write.label': '地図を管理', + 'oauth.scope.atlas:write.description': '訪問済みの国・地域を管理、バケットリスト編集', + 'oauth.scope.packing:read.label': '持ち物リストを表示', + 'oauth.scope.packing:read.description': '持ち物、バッグ、担当者を閲覧', + 'oauth.scope.packing:write.label': '持ち物リストを管理', + 'oauth.scope.packing:write.description': '持ち物やバッグの追加・編集・削除・並び替え', + 'oauth.scope.todos:read.label': 'ToDoリストを表示', + 'oauth.scope.todos:read.description': '旅行のToDoと担当者を閲覧', + 'oauth.scope.todos:write.label': 'ToDoリストを管理', + 'oauth.scope.todos:write.description': 'ToDoの作成・編集・完了・削除・並び替え', + 'oauth.scope.budget:read.label': '予算を表示', + 'oauth.scope.budget:read.description': '予算項目や内訳を閲覧', + 'oauth.scope.budget:write.label': '予算を管理', + 'oauth.scope.budget:write.description': '予算項目の作成・編集・削除', + 'oauth.scope.reservations:read.label': '予約を表示', + 'oauth.scope.reservations:read.description': '予約や宿泊情報を閲覧', + 'oauth.scope.reservations:write.label': '予約を管理', + 'oauth.scope.reservations:write.description': '予約の作成・編集・削除・並び替え', + 'oauth.scope.collab:read.label': 'コラボを表示', + 'oauth.scope.collab:read.description': '共同メモ、投票、メッセージを閲覧', + 'oauth.scope.collab:write.label': 'コラボを管理', + 'oauth.scope.collab:write.description': '共同メモ、投票、メッセージを管理', + 'oauth.scope.notifications:read.label': '通知を表示', + 'oauth.scope.notifications:read.description': 'アプリ内通知と未読数を閲覧', + 'oauth.scope.notifications:write.label': '通知を管理', + 'oauth.scope.notifications:write.description': '通知を既読にする・対応する', + 'oauth.scope.vacay:read.label': '休暇プランを表示', + 'oauth.scope.vacay:read.description': '休暇プランのデータや統計を閲覧', + 'oauth.scope.vacay:write.label': '休暇プランを管理', + 'oauth.scope.vacay:write.description': '休暇エントリーや予定を管理', + 'oauth.scope.geo:read.label': '地図・ジオコーディング', + 'oauth.scope.geo:read.description': '場所検索、地図URL解析、逆ジオコーディング', + 'oauth.scope.weather:read.label': '天気予報', + 'oauth.scope.weather:read.description': '旅行先・日程の天気予報を取得', + 'oauth.scope.journey:read.label': '日記を表示', + 'oauth.scope.journey:read.description': '日記、エントリー、参加者を閲覧', + 'oauth.scope.journey:write.label': '日記を管理', + 'oauth.scope.journey:write.description': '日記やエントリーの作成・編集・削除', + 'oauth.scope.journey:share.label': '日記共有を管理', + 'oauth.scope.journey:share.description': '公開共有リンクの作成・更新・無効化', + +// System notices — 3.0.0 upgrade + 'system_notice.v3_photos.title': '写真の場所が3.0で変更されました', + 'system_notice.v3_photos.body': '旅行プランナー内の写真は削除されましたが、写真データは安全です。TREKがImmichやSynologyのライブラリを変更することはありません。\n\n写真は現在日記アドオンにあります。日記は任意機能です。未有効の場合は、管理画面 → アドオンで有効にしてください。', + 'system_notice.v3_journey.title': '日記登場 — 旅の日記', + 'system_notice.v3_journey.body': 'タイムライン、写真ギャラリー、インタラクティブな地図で旅を物語に。', + 'system_notice.v3_journey.cta_label': '日記を開く', + 'system_notice.v3_journey.highlight_timeline': '日ごとのタイムラインとギャラリー', + 'system_notice.v3_journey.highlight_photos': 'ImmichやSynologyからインポート', + 'system_notice.v3_journey.highlight_share': 'ログイン不要で公開共有', + 'system_notice.v3_journey.highlight_export': 'PDFフォトブックとして書き出し', + 'system_notice.v3_features.title': '3.0のその他の注目点', + 'system_notice.v3_features.body': '今回のリリースで知っておきたいポイント。', + 'system_notice.v3_features.highlight_dashboard': 'モバイル重視のダッシュボード刷新', + 'system_notice.v3_features.highlight_offline': 'PWAとして完全オフライン対応', + 'system_notice.v3_features.highlight_search': 'リアルタイム場所検索', + 'system_notice.v3_features.highlight_import': 'KMZ/KMLから場所をインポート', + +// System notices — MCP OAuth 2.1 upgrade + 'system_notice.v3_mcp.title': 'MCP:OAuth 2.1に更新', + 'system_notice.v3_mcp.body': 'MCP連携が全面的に刷新されました。OAuth 2.1が推奨認証方式です。従来の静的トークン(trek_…)は非推奨となり、将来削除されます。', + 'system_notice.v3_mcp.highlight_oauth': 'OAuth 2.1推奨(mcp-remote)', + 'system_notice.v3_mcp.highlight_scopes': '24の詳細な権限スコープ', + 'system_notice.v3_mcp.highlight_deprecated': '静的trek_トークンは非推奨', + 'system_notice.v3_mcp.highlight_tools': 'ツールとプロンプトを拡張', + +// System notices — personal thank you + 'system_notice.v3_thankyou.title': '開発者より一言', + 'system_notice.v3_thankyou.body': '少しだけお時間をください。\n\nTREKは、自分の旅のために作った小さな個人プロジェクトでした。それが今では4,000人以上に使ってもらえるとは思ってもいませんでした。スターも、Issueも、機能要望も、すべて目を通しています。\n\nTREKはこれからもオープンソース、自分でホストでき、あなたのものです。トラッキングなし、サブスクなし。旅が好きな人が作ったツールです。\n\nhttps://github.com/jubnlにも感謝を。3.0の多くはあなたのおかげです。\n\nバグ報告、翻訳、共有、利用してくれたすべての方へ—本当にありがとうございます。\n\nこれからも一緒に旅を。\n\n— Maurice', + +// System notices — onboarding + 'system_notice.welcome_v1.title': 'TREKへようこそ', + 'system_notice.welcome_v1.body': 'オールインワンの旅行プランナー。旅程作成、共有、整理をオンライン・オフラインで。', + 'system_notice.welcome_v1.cta_label': '旅行を計画', + 'system_notice.welcome_v1.hero_alt': 'TREKのUIが重なった風景写真', + 'system_notice.welcome_v1.highlight_plan': '日ごとの旅程作成', + 'system_notice.welcome_v1.highlight_share': '仲間と共同編集', + 'system_notice.welcome_v1.highlight_offline': 'モバイルでオフライン対応', + 'system_notice.dev_test_modal.title': '[Dev] テスト通知', + 'system_notice.dev_test_modal.body': 'これは開発用テスト通知です。', + 'system_notice.pager.prev': '前へ', + 'system_notice.pager.next': '次へ', + 'system_notice.pager.counter': '{current} / {total}', + 'system_notice.pager.goto': '通知{n}へ', + 'system_notice.pager.position': '{total}件中{current}件目', + 'transport.addTransport': '移動手段を追加', + 'transport.modalTitle.create': '移動手段を追加', + 'transport.modalTitle.edit': '移動手段を編集', + 'transport.title': '移動手段', + 'transport.addManual': '手動で追加', +} + +export default ja diff --git a/client/tests/unit/i18n/index.test.ts b/client/tests/unit/i18n/index.test.ts index c042debd1..17e306fe8 100644 --- a/client/tests/unit/i18n/index.test.ts +++ b/client/tests/unit/i18n/index.test.ts @@ -91,7 +91,7 @@ describe('isRtlLanguage', () => { describe('SUPPORTED_LANGUAGES', () => { it('FE-COMP-I18N-009: contains expected entries with value/label shape', () => { expect(Array.isArray(SUPPORTED_LANGUAGES)).toBe(true) - expect(SUPPORTED_LANGUAGES).toHaveLength(15) + expect(SUPPORTED_LANGUAGES).toHaveLength(16) expect(SUPPORTED_LANGUAGES).toContainEqual(expect.objectContaining({ value: 'en', label: 'English' })) expect(SUPPORTED_LANGUAGES).toContainEqual(expect.objectContaining({ value: 'ar', label: 'العربية' })) })