From ba9936f90acec64d704f8b625e1f861f78c36633 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 24 Sep 2026 16:34:13 +0200 Subject: [PATCH] feat(i18n): add Thai (th) translation --- client/src/i18n/TranslationContext.tsx | 1 + shared/src/i18n/languages.ts | 1 + shared/src/i18n/th/admin.ts | 765 ++++++++++++++++++++ shared/src/i18n/th/airport.ts | 6 + shared/src/i18n/th/atlas.ts | 65 ++ shared/src/i18n/th/backup.ts | 72 ++ shared/src/i18n/th/budget.ts | 163 +++++ shared/src/i18n/th/categories.ts | 25 + shared/src/i18n/th/collab.ts | 97 +++ shared/src/i18n/th/collection.ts | 207 ++++++ shared/src/i18n/th/common.ts | 77 ++ shared/src/i18n/th/dashboard.ts | 189 +++++ shared/src/i18n/th/dawarich.ts | 153 ++++ shared/src/i18n/th/day.ts | 26 + shared/src/i18n/th/dayplan.ts | 93 +++ shared/src/i18n/th/externalNotifications.ts | 77 ++ shared/src/i18n/th/files.ts | 66 ++ shared/src/i18n/th/help.ts | 12 + shared/src/i18n/th/index.ts | 112 +++ shared/src/i18n/th/inspector.ts | 30 + shared/src/i18n/th/journey.ts | 646 +++++++++++++++++ shared/src/i18n/th/login.ts | 76 ++ shared/src/i18n/th/map.ts | 30 + shared/src/i18n/th/members.ts | 38 + shared/src/i18n/th/memories.ts | 75 ++ shared/src/i18n/th/mobileAdmin.ts | 9 + shared/src/i18n/th/mobileAtlas.ts | 8 + shared/src/i18n/th/mobileCollections.ts | 7 + shared/src/i18n/th/mobileJourney.ts | 17 + shared/src/i18n/th/mobileNav.ts | 9 + shared/src/i18n/th/mobileSettings.ts | 7 + shared/src/i18n/th/mobileTrip.ts | 69 ++ shared/src/i18n/th/mobileVacay.ts | 19 + shared/src/i18n/th/nav.ts | 21 + shared/src/i18n/th/notif.ts | 50 ++ shared/src/i18n/th/notifications.ts | 36 + shared/src/i18n/th/oauth.ts | 113 +++ shared/src/i18n/th/packing.ts | 213 ++++++ shared/src/i18n/th/pdf.ts | 14 + shared/src/i18n/th/perm.ts | 51 ++ shared/src/i18n/th/photos.ts | 25 + shared/src/i18n/th/places.ts | 136 ++++ shared/src/i18n/th/planner.ts | 67 ++ shared/src/i18n/th/register.ts | 25 + shared/src/i18n/th/reservations.ts | 181 +++++ shared/src/i18n/th/roadtrip.ts | 249 +++++++ shared/src/i18n/th/settings.ts | 588 +++++++++++++++ shared/src/i18n/th/share.ts | 16 + shared/src/i18n/th/shared.ts | 21 + shared/src/i18n/th/stats.ts | 13 + shared/src/i18n/th/storage.ts | 153 ++++ shared/src/i18n/th/system_notice.ts | 84 +++ shared/src/i18n/th/todo.ts | 41 ++ shared/src/i18n/th/transport.ts | 10 + shared/src/i18n/th/trip.ts | 92 +++ shared/src/i18n/th/trips.ts | 16 + shared/src/i18n/th/undo.ts | 24 + shared/src/i18n/th/vacay.ts | 149 ++++ 58 files changed, 5635 insertions(+) create mode 100644 shared/src/i18n/th/admin.ts create mode 100644 shared/src/i18n/th/airport.ts create mode 100644 shared/src/i18n/th/atlas.ts create mode 100644 shared/src/i18n/th/backup.ts create mode 100644 shared/src/i18n/th/budget.ts create mode 100644 shared/src/i18n/th/categories.ts create mode 100644 shared/src/i18n/th/collab.ts create mode 100644 shared/src/i18n/th/collection.ts create mode 100644 shared/src/i18n/th/common.ts create mode 100644 shared/src/i18n/th/dashboard.ts create mode 100644 shared/src/i18n/th/dawarich.ts create mode 100644 shared/src/i18n/th/day.ts create mode 100644 shared/src/i18n/th/dayplan.ts create mode 100644 shared/src/i18n/th/externalNotifications.ts create mode 100644 shared/src/i18n/th/files.ts create mode 100644 shared/src/i18n/th/help.ts create mode 100644 shared/src/i18n/th/index.ts create mode 100644 shared/src/i18n/th/inspector.ts create mode 100644 shared/src/i18n/th/journey.ts create mode 100644 shared/src/i18n/th/login.ts create mode 100644 shared/src/i18n/th/map.ts create mode 100644 shared/src/i18n/th/members.ts create mode 100644 shared/src/i18n/th/memories.ts create mode 100644 shared/src/i18n/th/mobileAdmin.ts create mode 100644 shared/src/i18n/th/mobileAtlas.ts create mode 100644 shared/src/i18n/th/mobileCollections.ts create mode 100644 shared/src/i18n/th/mobileJourney.ts create mode 100644 shared/src/i18n/th/mobileNav.ts create mode 100644 shared/src/i18n/th/mobileSettings.ts create mode 100644 shared/src/i18n/th/mobileTrip.ts create mode 100644 shared/src/i18n/th/mobileVacay.ts create mode 100644 shared/src/i18n/th/nav.ts create mode 100644 shared/src/i18n/th/notif.ts create mode 100644 shared/src/i18n/th/notifications.ts create mode 100644 shared/src/i18n/th/oauth.ts create mode 100644 shared/src/i18n/th/packing.ts create mode 100644 shared/src/i18n/th/pdf.ts create mode 100644 shared/src/i18n/th/perm.ts create mode 100644 shared/src/i18n/th/photos.ts create mode 100644 shared/src/i18n/th/places.ts create mode 100644 shared/src/i18n/th/planner.ts create mode 100644 shared/src/i18n/th/register.ts create mode 100644 shared/src/i18n/th/reservations.ts create mode 100644 shared/src/i18n/th/roadtrip.ts create mode 100644 shared/src/i18n/th/settings.ts create mode 100644 shared/src/i18n/th/share.ts create mode 100644 shared/src/i18n/th/shared.ts create mode 100644 shared/src/i18n/th/stats.ts create mode 100644 shared/src/i18n/th/storage.ts create mode 100644 shared/src/i18n/th/system_notice.ts create mode 100644 shared/src/i18n/th/todo.ts create mode 100644 shared/src/i18n/th/transport.ts create mode 100644 shared/src/i18n/th/trip.ts create mode 100644 shared/src/i18n/th/trips.ts create mode 100644 shared/src/i18n/th/undo.ts create mode 100644 shared/src/i18n/th/vacay.ts diff --git a/client/src/i18n/TranslationContext.tsx b/client/src/i18n/TranslationContext.tsx index f6dc29365..32c4973b2 100644 --- a/client/src/i18n/TranslationContext.tsx +++ b/client/src/i18n/TranslationContext.tsx @@ -38,6 +38,7 @@ const localeLoaders: Record Promise<{ default: Tran pl: () => import('@trek/shared/i18n/pl'), ja: () => import('@trek/shared/i18n/ja'), ko: () => import('@trek/shared/i18n/ko'), + th: () => import('@trek/shared/i18n/th'), uk: () => import('@trek/shared/i18n/uk'), gr: () => import('@trek/shared/i18n/gr'), sv: () => import('@trek/shared/i18n/sv'), diff --git a/shared/src/i18n/languages.ts b/shared/src/i18n/languages.ts index e1b65dcea..0f3825a1d 100644 --- a/shared/src/i18n/languages.ts +++ b/shared/src/i18n/languages.ts @@ -20,6 +20,7 @@ export const SUPPORTED_LANGUAGES = [ { value: 'id', label: 'Bahasa Indonesia', locale: 'id-ID' }, { value: 'ja', label: '日本語', locale: 'ja-JP' }, { value: 'ko', label: '한국어', locale: 'ko-KR' }, + { value: 'th', label: 'ไทย', locale: 'th-TH' }, { value: 'uk', label: 'Українська', locale: 'uk-UA' }, { value: 'gr', label: 'Ελληνικά', locale: 'el-GR' }, { value: 'sv', label: 'Svenska', locale: 'sv-SE' }, diff --git a/shared/src/i18n/th/admin.ts b/shared/src/i18n/th/admin.ts new file mode 100644 index 000000000..990137fa7 --- /dev/null +++ b/shared/src/i18n/th/admin.ts @@ -0,0 +1,765 @@ +import type { TranslationStrings } from '../types'; + +const admin: TranslationStrings = { + 'admin.notifications.title': "การแจ้งเตือน", + 'admin.notifications.hint': "เลือกช่องทางการแจ้งเตือนหนึ่งช่องทาง สามารถใช้งานได้ครั้งละหนึ่งรายการเท่านั้น", + 'admin.notifications.none': "ปิดการใช้งาน", + 'admin.notifications.email': "อีเมล์ (SMTP)", + 'admin.notifications.webhook': "เว็บฮุค", + 'admin.notifications.ntfy': "เอ็นทีฟี่", + 'admin.ntfy.hint': + "อนุญาตให้ผู้ใช้กำหนดค่าหัวข้อ ntfy ของตนเองสำหรับการแจ้งเตือนแบบพุช ตั้งค่าเซิร์ฟเวอร์เริ่มต้นด้านล่างเพื่อกรอกการตั้งค่าผู้ใช้ล่วงหน้า", + 'admin.notifications.save': "บันทึกการตั้งค่าการแจ้งเตือน", + 'admin.notifications.saved': "บันทึกการตั้งค่าการแจ้งเตือนแล้ว", + 'admin.notifications.testWebhook': "ส่งเว็บฮุคทดสอบ", + 'admin.notifications.testWebhookSuccess': "ส่งเว็บฮุคทดสอบเรียบร้อยแล้ว", + 'admin.notifications.testWebhookFailed': "การทดสอบเว็บฮุคล้มเหลว", + 'admin.notifications.testNtfy': "ส่งการทดสอบ ntfy", + 'admin.notifications.testNtfySuccess': "ทดสอบการส่ง ntfy สำเร็จ", + 'admin.notifications.testNtfyFailed': "การทดสอบ ntfy ล้มเหลว", + 'admin.notifications.emailPanel.title': "อีเมล์ (SMTP)", + 'admin.notifications.webhookPanel.title': "เว็บฮุค", + 'admin.notifications.inappPanel.title': "ในแอป", + 'admin.notifications.inappPanel.hint': "การแจ้งเตือนในแอปจะทำงานอยู่เสมอและไม่สามารถปิดใช้งานได้ทั่วโลก", + 'admin.notifications.adminWebhookPanel.title': "แอดมินเว็บฮุค", + 'admin.notifications.adminWebhookPanel.hint': + "เว็บฮุคนี้ใช้สำหรับการแจ้งเตือนของผู้ดูแลระบบโดยเฉพาะ (เช่น การแจ้งเตือนเวอร์ชัน) แยกจาก webhooks ต่อผู้ใช้และจะเริ่มทำงานเสมอเมื่อตั้งค่า", + 'admin.notifications.adminWebhookPanel.saved': "บันทึก URL ของเว็บฮุคของผู้ดูแลระบบแล้ว", + 'admin.notifications.adminWebhookPanel.testSuccess': "ส่งเว็บฮุคทดสอบเรียบร้อยแล้ว", + 'admin.notifications.adminWebhookPanel.testFailed': "การทดสอบเว็บฮุคล้มเหลว", + 'admin.notifications.adminWebhookPanel.alwaysOnHint': "Admin webhook จะเริ่มทำงานเสมอเมื่อมีการกำหนดค่า URL", + 'admin.notifications.adminNtfyPanel.title': "แอดมิน Ntfy", + 'admin.notifications.adminNtfyPanel.hint': + "หัวข้อ ntfy นี้ใช้สำหรับการแจ้งเตือนของผู้ดูแลระบบโดยเฉพาะ (เช่น การแจ้งเตือนเวอร์ชัน) แยกจากหัวข้อต่อผู้ใช้และเริ่มทำงานเสมอเมื่อมีการกำหนดค่า", + 'admin.notifications.adminNtfyPanel.serverLabel': "URL เซิร์ฟเวอร์ ntfy", + 'admin.notifications.adminNtfyPanel.serverHint': + "ยังใช้เป็นเซิร์ฟเวอร์เริ่มต้นสำหรับการแจ้งเตือนผู้ใช้ ntfy เว้นว่างไว้เป็นค่าเริ่มต้นเป็น ntfy.sh ผู้ใช้สามารถแทนที่สิ่งนี้ได้ในการตั้งค่าของตนเอง", + 'admin.notifications.adminNtfyPanel.serverPlaceholder': "https://ntfy.sh", + 'admin.notifications.adminNtfyPanel.topicLabel': "หัวข้อผู้ดูแลระบบ", + 'admin.notifications.adminNtfyPanel.topicPlaceholder': "การแจ้งเตือนผู้ดูแลระบบ Trek", + 'admin.notifications.adminNtfyPanel.tokenLabel': "โทเค็นการเข้าถึง (ไม่จำเป็น)", + 'admin.notifications.adminNtfyPanel.tokenCleared': "ล้างโทเค็นการเข้าถึงของผู้ดูแลระบบแล้ว", + 'admin.notifications.adminNtfyPanel.saved': "บันทึกการตั้งค่าผู้ดูแลระบบแล้ว", + 'admin.notifications.adminNtfyPanel.test': "ส่งการทดสอบ ntfy", + 'admin.notifications.adminNtfyPanel.testSuccess': "ทดสอบการส่ง ntfy สำเร็จ", + 'admin.notifications.adminNtfyPanel.testFailed': "การทดสอบ ntfy ล้มเหลว", + 'admin.notifications.adminNtfyPanel.alwaysOnHint': "ผู้ดูแลระบบ ntfy จะเริ่มทำงานเสมอเมื่อมีการกำหนดค่าหัวข้อ", + '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': "อนุญาตให้ผู้ใช้กำหนดค่า URL ของเว็บฮุคของตนเองสำหรับการแจ้งเตือน (Discord, Slack ฯลฯ)", + 'admin.smtp.testSuccess': "ส่งอีเมลทดสอบเรียบร้อยแล้ว", + 'admin.smtp.testFailed': "อีเมลทดสอบล้มเหลว", + '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': "ต้องเปิดใช้งานวิธีการเข้าสู่ระบบอย่างน้อยหนึ่งวิธี", + '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 คุณจะดูรูปภาพ คะแนน และเวลาเปิดทำการได้ คีย์นี้สร้างได้ที่ console.cloud.google.com", + 'admin.recommended': "แนะนำ", + 'admin.weatherKey': "คีย์ API ของ OpenWeatherMap", + 'admin.weatherKeyHint': "สำหรับข้อมูลสภาพอากาศ ฟรีที่ openweathermap.org", + 'admin.unsplashKey': "Unsplash คีย์ API", + 'admin.unsplashKeyHint': "สำหรับการค้นหาภาพ ฟรีที่ unsplash.com/developers", + 'admin.validateKey': "ทดสอบ", + 'admin.keyValid': "เชื่อมต่อแล้ว", + 'admin.keyInvalid': "ไม่ถูกต้อง", + 'admin.keySaved': "บันทึกคีย์ API แล้ว", + 'admin.oidcTitle': "การลงชื่อเพียงครั้งเดียว (OIDC)", + 'admin.oidcSubtitle': "อนุญาตให้เข้าสู่ระบบผ่านผู้ให้บริการภายนอก เช่น Google, Apple, Authentik หรือ Keycloak", + 'admin.oidcDisplayName': "ชื่อที่แสดง", + 'admin.oidcIssuer': "URL ของผู้ออก", + 'admin.oidcIssuerHint': "URL ผู้ออก OpenID Connect ของผู้ให้บริการ เช่น https://accounts.google.com", + 'admin.oidcSaved': "บันทึกการกำหนดค่า OIDC แล้ว", + 'admin.oidcOnlyMode': "ปิดการใช้งานการตรวจสอบรหัสผ่าน", + 'admin.oidcOnlyModeHint': + "เมื่อเปิดใช้งาน จะอนุญาตเฉพาะการเข้าสู่ระบบ SSO เท่านั้น การเข้าสู่ระบบและการลงทะเบียนด้วยรหัสผ่านถูกบล็อก", + 'admin.fileTypes': "ประเภทไฟล์ที่อนุญาต", + 'admin.fileTypesHint': "กำหนดค่าประเภทไฟล์ที่ผู้ใช้สามารถอัปโหลดได้", + 'admin.fileTypesFormat': "ส่วนขยายที่คั่นด้วยเครื่องหมายจุลภาค (เช่น jpg,png,pdf,doc) ใช้ * เพื่ออนุญาตทุกประเภท", + 'admin.fileTypesSaved': "บันทึกการตั้งค่าประเภทไฟล์แล้ว", + 'admin.placesPhotos.title': "รูปภาพสถานที่", + 'admin.placesPhotos.subtitle': + "ดึงรูปภาพจาก Google Places API ปิดใช้เพื่อบันทึกโควต้า API ภาพถ่ายวิกิมีเดียไม่ได้รับผลกระทบ", + 'admin.placesAutocomplete.title': "การเติมคำอัตโนมัติสำหรับสถานที่", + 'admin.placesAutocomplete.subtitle': "ใช้ Google Places API เพื่อแนะนำการค้นหา ปิดใช้เพื่อบันทึกโควต้า API", + 'admin.placesDetails.title': "รายละเอียดสถานที่", + 'admin.placesDetails.subtitle': + "ดึงข้อมูลสถานที่โดยละเอียด (ชั่วโมง คะแนน เว็บไซต์) จาก Google Places API ปิดใช้เพื่อบันทึกโควต้า API", + 'admin.placesEnrich.title': "สถานที่เสริมคุณค่า", + 'admin.placesEnrich.subtitle': + "แสดงรูปภาพและคำอธิบายขณะเพิ่มสถานที่ มีการใช้ Wikipedia และ OpenStreetMap เสมอ Google จะถูกเพิ่มไว้ด้านบนเมื่อเปิดรูปภาพสถานที่หรือรายละเอียดสถานที่", + '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.defaultSettings.mapProvider': "เครื่องยนต์แผนที่", + 'admin.defaultSettings.mapProviderHint': + "แผนที่เริ่มต้นสำหรับผู้ใช้ทุกคนในอินสแตนซ์นี้ ผู้ใช้แต่ละคนยังสามารถแทนที่ในการตั้งค่าของตนเองได้", + 'admin.defaultSettings.providerLeaflet': "มาตรฐาน (ฟรี)", + 'admin.defaultSettings.providerMapbox': "Mapbox (3D)", + 'admin.defaultSettings.providerMapLibre': "MapLibre (OpenFreeMap)", + 'admin.defaultSettings.mapboxToken': "โทเค็น Mapbox ที่ใช้ร่วมกัน", + 'admin.defaultSettings.mapboxTokenHint': + "ใช้สำหรับผู้ใช้ทุกคนที่ไม่ได้ป้อนโทเค็นของตนเอง — ดังนั้นอินสแตนซ์ทั้งหมดจะได้รับ Mapbox โดยไม่ต้องแชร์คีย์ทีละรายการ จัดเก็บแบบเข้ารหัส", + 'admin.defaultSettings.mapboxStyle': "รูปแบบแผนที่", + 'admin.defaultSettings.mapboxStylePlaceholder': "เลือกสไตล์...", + 'admin.defaultSettings.mapbox3d': "สิ่งปลูกสร้าง 3 มิติและภูมิประเทศ", + 'admin.defaultSettings.mapboxQuality': "โหมดคุณภาพสูง", + 'admin.defaultSettings.cartoKey': "คีย์ CARTO ที่ใช้ร่วมกัน", + 'admin.defaultSettings.cartoKeyHint': + "ใช้สำหรับผู้ใช้ทุกคนที่ไม่ได้ป้อนรหัสของตนเอง ดังนั้นอินสแตนซ์ทั้งหมดจึงได้รับไทล์ CARTO โดยไม่มีลายน้ำ จัดเก็บแบบเข้ารหัส", + 'admin.tabs.templates': "เทมเพลตการบรรจุ", + 'admin.packingTemplates.title': "เทมเพลตการบรรจุ", + 'admin.packingTemplates.subtitle': "สร้างรายการจัดกระเป๋าที่นำกลับมาใช้ใหม่ได้สำหรับการเดินทางของคุณ", + 'admin.packingTemplates.create': "เทมเพลตใหม่", + 'admin.packingTemplates.namePlaceholder': "ชื่อเทมเพลต (เช่น Beach Holiday)", + '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.deleteCategoryError': "ลบหมวดหมู่ไม่สำเร็จ", + 'admin.packingTemplates.deleteItemError': "ลบรายการไม่สำเร็จ", + 'admin.packingTemplates.saveError': "บันทึกไม่สำเร็จ", + 'admin.tabs.addons': "ส่วนเสริม", + 'admin.tabs.plugins': "ปลั๊กอิน", + 'admin.tabs.storage': "ที่เก็บของ", + 'admin.plugins.rescan': "สแกนอีกครั้ง", + 'admin.plugins.rescanned': "สแกนโฟลเดอร์ปลั๊กอินอีกครั้ง", + 'admin.plugins.upload': "อัปโหลดปลั๊กอิน", + 'admin.plugins.dropToUpload': "วางปลั๊กอิน .zip เพื่อติดตั้ง", + 'admin.plugins.uploaded': "อัปโหลดปลั๊กอิน “{name}” แล้ว — เปิดใช้งานเพื่อให้ทำงานได้", + 'admin.plugins.sideloaded': "ไซด์โหลด", + 'admin.plugins.devLinkBadge': "Dev-Link", + 'admin.plugins.devLinkHint': "โหลดจากไดเร็กทอรี build ในเครื่องและรีโหลดแบบ hot-reload กับข้อมูลจริง — dev เท่านั้น", + 'admin.plugins.devLinkTitle': "เชื่อมโยงปลั๊กอินท้องถิ่น", + 'admin.plugins.devLinkPathPlaceholder': "/absolute/path/to/your/plugin", + 'admin.plugins.devLinkButton': "ลิงก์", + 'admin.plugins.devLinkLinked': "เชื่อมโยง {id} — เปิดใช้งานเพื่อเรียกใช้", + 'admin.plugins.sideloadedHint': "อัปโหลดด้วยตนเอง — ไม่ได้มาจากรายการทะเบียน ไม่ได้ลงนามและยังไม่ได้ตรวจสอบ", + 'admin.plugins.browse': "เรียกดูปลั๊กอิน", + 'admin.plugins.installed': "ติดตั้งแล้ว", + 'admin.plugins.install': "ติดตั้ง", + 'admin.plugins.registryEmpty': "ยังไม่มีปลั๊กอินในรีจิสทรี", + 'admin.plugins.actionError': "การดำเนินการล้มเหลว", + 'admin.plugins.activate': "เปิดใช้งาน", + 'admin.plugins.activated': "เปิดใช้งานปลั๊กอินแล้ว", + 'admin.plugins.deactivate': "ปิดการใช้งาน", + 'admin.plugins.deactivated': "ปิดใช้งานปลั๊กอินแล้ว", + 'admin.plugins.viewErrors': "ดูบันทึกข้อผิดพลาด", + 'admin.plugins.errorLog': "บันทึกข้อผิดพลาด", + 'admin.plugins.allowedHosts': "โฮสต์ที่ได้รับอนุญาต", + 'admin.plugins.allowedHosts.hint': + "ปลั๊กอินนี้เชื่อมต่อกับบริการที่มีเพียงคุณเท่านั้นที่ระบุได้ เพิ่มโฮสต์ที่อนุญาตให้เชื่อมต่อได้ — นอกเหนือจากนั้นจะเชื่อมต่อไม่ได้", + 'admin.plugins.allowedHosts.none': "ยังไม่ได้เพิ่มโฮสต์", + 'admin.plugins.allowedHosts.unsupported': + "ปลั๊กอินนี้ไม่ได้ใช้โฮสต์ที่ผู้ดูแลระบุ โฮสต์ที่อนุญาตถูกกำหนดไว้ตายตัวใน manifest", + 'admin.plugins.allowedHosts.restartNote': "การบันทึกจะรีสตาร์ทปลั๊กอินเพื่อให้เลือกรายการใหม่", + 'admin.plugins.allowedHosts.add': "เพิ่มโฮสต์ที่ได้รับอนุญาต", + 'admin.plugins.allowedHosts.count': "{n} โฮสต์ที่อนุญาต", + 'admin.plugins.operatorEgressPill': "+ โฮสต์ที่คุณเพิ่ม", + 'admin.plugins.operatorEgressHint': + "ปลั๊กอินนี้เชื่อมต่อกับบริการที่มีเพียงคุณเท่านั้นที่ระบุได้ หลังจากติดตั้งแล้ว ให้เพิ่มโฮสต์ที่อนุญาตใน ⋯ → โฮสต์ที่อนุญาต นอกเหนือจากนั้นจะเชื่อมต่อไม่ได้", + 'admin.plugins.noErrors': "ไม่มีการบันทึกข้อผิดพลาด", + 'admin.plugins.uninstalled': "ถอนการติดตั้งปลั๊กอินแล้ว", + 'admin.plugins.uninstallTitle': "ถอนการติดตั้งปลั๊กอินใช่ไหม", + 'admin.plugins.uninstallBody': + "การดำเนินการนี้จะหยุดปลั๊กอิน ลบโค้ด และลบข้อมูลทั้งหมด สิ่งนี้ไม่สามารถยกเลิกได้", + 'admin.plugins.status.starting': "กำลังเริ่ม...", + 'admin.plugins.type.widget': "วิดเจ็ต", + 'admin.plugins.type.page': "หน้า", + 'admin.plugins.type.integration': "การเชื่อมต่อ", + 'admin.plugins.type.trip-page': "หน้าทริป", + 'admin.plugins.reviewed': "ตรวจสอบแล้ว", + 'admin.plugins.unreviewed': "ไม่ได้รับการตรวจทาน", + 'admin.plugins.updated': "อัปเดตปลั๊กอินแล้ว", + 'admin.plugins.updateTo': "อัปเดต → v{version}", + 'admin.plugins.enabledToggle': "เปิดใช้งานปลั๊กอิน", + 'plugins.notFound': "ไม่พบปลั๊กอิน", + 'plugins.frameLoadFailed': "ไม่สามารถโหลดปลั๊กอินนี้ได้", + 'admin.plugins.title': "ปลั๊กอิน", + 'admin.plugins.subtitle': "ติดตั้งและจัดการปลั๊กอินของบริษัทอื่นบนอินสแตนซ์ของคุณ", + 'admin.plugins.disabledTitle': "ปลั๊กอินถูกปิดใช้งาน", + 'admin.plugins.disabledBody': + "รันไทม์ปลั๊กอินปิดอยู่ (TREK_PLUGINS_ENABLED) ไม่มีปลั๊กอินใดทำงานจนกว่าผู้ดูแลระบบจะเปิดใช้งานในการกำหนดค่าเซิร์ฟเวอร์", + 'admin.plugins.empty': "ยังไม่มีการติดตั้งปลั๊กอิน", + 'admin.plugins.loadError': "ไม่สามารถโหลดปลั๊กอินได้", + 'admin.plugins.scaffoldNote': + "การติดตั้งและการเปิดใช้งานปลั๊กอินจะมาในการอัปเดตในภายหลัง ปัจจุบันแผงนี้แสดงรายการปลั๊กอินที่ติดตั้งเท่านั้น", + 'admin.plugins.status.active': "ใช้งานอยู่", + 'admin.plugins.status.inactive': "ไม่ได้ใช้งาน", + 'admin.plugins.status.disabled': "ปิดการใช้งาน", + 'admin.plugins.status.error': "เกิดข้อผิดพลาด", + 'admin.plugins.status.incompatible': "เข้ากันไม่ได้", + 'admin.plugins.details': "รายละเอียด", + 'admin.plugins.detailError': "ไม่สามารถโหลดรายละเอียดปลั๊กอินได้", + 'admin.plugins.permissionsTitle': "สิทธิ์", + 'admin.plugins.noPermissions': "ปลั๊กอินนี้ไม่ขอสิทธิ์พิเศษ", + 'admin.plugins.egressNote': "อาจเชื่อมต่อกับ: {hosts}", + 'admin.plugins.setupTitle': "ตั้งค่า", + 'admin.plugins.noSetup': "ใช้งานได้ทันที — ไม่มีอะไรต้องกำหนดค่า", + 'admin.plugins.scope.instance': "ทั่วทั้งอินสแตนซ์", + 'admin.plugins.scope.user': "ต่อผู้ใช้", + 'admin.plugins.fieldRequired': "จำเป็น", + 'admin.plugins.sourceRepo': "แหล่งเก็บข้อมูล", + 'admin.plugins.reportIssue': "รายงานปัญหา", + 'admin.plugins.homepage': "หน้าแรก", + 'admin.plugins.requiresTrek': "ต้องใช้ TREK {version}+", + 'admin.plugins.reviewedOn': "ตรวจสอบเมื่อ {date}", + 'admin.plugins.perm.db:own': "เก็บข้อมูลของตัวเองไว้ในฐานข้อมูลแบบแยกส่วน", + 'admin.plugins.perm.db:read:trips': "อ่านการเดินทางที่ผู้ใช้บริการสามารถเข้าถึงได้", + 'admin.plugins.perm.db:read:users': "อ่านข้อมูลโปรไฟล์พื้นฐาน (ชื่อ อวตาร — ไม่ต้องระบุข้อมูลประจำตัว)", + 'admin.plugins.perm.db:read:costs': "อ่านต้นทุน (รายการงบประมาณ) ที่ผู้ใช้ที่ดำเนินการสามารถเข้าถึงได้", + 'admin.plugins.perm.db:read:packing': "อ่านรายการจัดกระเป๋าของทริปที่ผู้ใช้บริการเข้าถึงได้", + 'admin.plugins.perm.db:write:packing': "สร้าง แก้ไข และลบรายการจัดกระเป๋าในทริปที่ผู้ใช้บริการแก้ไขได้", + 'admin.plugins.perm.weather:read': "อ่านพยากรณ์อากาศแคชของโฮสต์ (ตามพิกัด)", + 'admin.plugins.perm.db:read:categories': "อ่านรายการหมวดหมู่สถานที่ทั่วโลก", + 'admin.plugins.perm.db:read:tags': "อ่านแท็กของผู้ใช้ที่ทำหน้าที่เอง", + 'admin.plugins.perm.db:write:tags': "สร้าง แก้ไข และลบแท็กของผู้ใช้ที่ทำหน้าที่เอง", + 'admin.plugins.perm.db:read:todos': "อ่านสิ่งที่ต้องทำของการเดินทางที่ผู้ใช้บริการสามารถเข้าถึงได้", + 'admin.plugins.perm.db:write:todos': "สร้าง แก้ไข และลบสิ่งที่ต้องทำในการเดินทางที่ผู้ใช้ที่ดำเนินการสามารถแก้ไขได้", + 'admin.plugins.perm.db:write:atlas': + "ทำเครื่องหมายประเทศและภูมิภาคที่เยี่ยมชมและจัดการรายชื่อผู้ใช้ที่ดำเนินการ (ต้องการ Atlas addon)", + 'admin.plugins.perm.db:write:vacay': + "สลับวันลาพักร้อนและวันหยุดบริษัทตามแผนที่ใช้งานอยู่ของผู้ใช้ที่รักษาการ (ต้องการ Vacay addon)", + 'admin.plugins.perm.db:write:journal': + "สร้าง แก้ไข และลบรายการบันทึกประจำวัน และแนบรูปถ่ายในการเดินทางที่ผู้ใช้ดำเนินการสามารถแก้ไขได้ (ต้องการส่วนเสริม Journey)", + 'admin.plugins.perm.db:write:collections': + "สร้างและแก้ไขคอลเลกชันและบันทึกสถานที่ลงในคอลเลกชันเหล่านั้น โดยมีบทบาทคอลเลกชันของผู้ใช้ที่ทำหน้าที่ (ต้องการส่วนเสริมคอลเลกชัน)", + 'admin.plugins.perm.db:write:files': + "แนบไฟล์ไปกับการเดินทางที่ผู้ใช้ดำเนินการสามารถแก้ไขได้ (สูงสุด 10MB ส่วนขยายที่ถูกบล็อกถูกปฏิเสธ) และจัดการลิงก์ของพวกเขา", + 'admin.plugins.perm.db:write:collab': + "โพสต์บันทึก โพล และข้อความแชทในการเดินทางที่ผู้ใช้ดำเนินการสามารถแก้ไขได้ (ต้องการส่วนเสริม Collab)", + 'admin.plugins.perm.db:write:members': + "เพิ่มผู้ใช้ในการเดินทาง — ให้สิทธิ์การเข้าถึงการเดินทาง ล้อมรอบโดยสิทธิ์ในการจัดการสมาชิกของผู้ใช้ที่รักษาการ", + 'admin.plugins.perm.notify:send': + "ส่งการแจ้งเตือน (กล่องจดหมายรูประฆัง + อีเมล/ntfy) ไปยังผู้ใช้ที่ดำเนินการหรือการเดินทางที่พวกเขาอยู่ - ไม่เคยเป็นผู้รับโดยพลการ", + 'admin.plugins.perm.ai:invoke': + "เรียกใช้ผู้ให้บริการ AI ที่กำหนดค่าโดยผู้ดูแลระบบ (การเติมข้อความ + การแยกเอกสาร) ในนามของผู้ใช้ที่ทำหน้าที่ — ปลั๊กอินไม่เคยเก็บคีย์ไว้", + 'admin.plugins.perm.oauth:client': + "เชื่อมต่อกับบริการของบุคคลที่สามในนามของคุณผ่าน OAuth ที่เป็นนายหน้าโฮสต์ (โฮสต์ถือโทเค็น ปลั๊กอินจะไม่เคยเห็นโทเค็นเหล่านั้นเลย)", + 'admin.plugins.perm.db:read:files': "อ่านไฟล์ของทริปที่ผู้ใช้ที่กำลังดำเนินการเข้าถึงได้", + 'admin.plugins.perm.db:read:journal': "อ่านบันทึกการเดินทางของผู้ใช้บริการ (ต้องการ Addon Journey)", + 'admin.plugins.perm.db:read:atlas': + "อ่านประเทศและภูมิภาคที่เยี่ยมชมของผู้ใช้ที่ทำหน้าที่ (ต้องการ Atlas addon)", + 'admin.plugins.perm.db:read:vacay': "อ่านแผนวันหยุดของผู้ใช้ที่ทำหน้าที่ (ต้องการ Vacay addon)", + 'admin.plugins.perm.db:read:daynotes': "อ่านบันทึกประจำวันของทริปที่ผู้ใช้ที่กำลังดำเนินการเข้าถึงได้", + 'admin.plugins.perm.db:read:collections': + "อ่านคอลเลกชันสถานที่ที่บันทึกไว้ของผู้ใช้ที่ทำหน้าที่ (ต้องการส่วนเสริมคอลเลกชัน)", + 'admin.plugins.perm.db:write:costs': "สร้างต้นทุน (รายการงบประมาณ) ในการเดินทางที่ผู้ใช้ที่ดำเนินการสามารถแก้ไขได้", + 'admin.plugins.perm.db:write:places': "เพิ่ม แก้ไข และลบสถานที่ในทริปที่ผู้ใช้ที่กำลังดำเนินการแก้ไขได้", + 'admin.plugins.perm.db:write:days': "เพิ่ม แก้ไข และลบวันในทริปที่ผู้ใช้ที่กำลังดำเนินการแก้ไขได้", + 'admin.plugins.perm.db:write:itinerary': "กำหนดและลบสถานที่ในวันที่เดินทางซึ่งผู้ใช้ที่ดำเนินการสามารถแก้ไขได้", + 'admin.plugins.perm.db:write:trips': "แก้ไขรายละเอียดทริป (ชื่อ วันที่ สกุลเงิน…) ในทริปที่ผู้ใช้ที่กำลังดำเนินการแก้ไขได้", + 'admin.plugins.perm.db:write:reservations': + "สร้าง แก้ไข และลบการจองในทริปที่ผู้ใช้ที่กำลังดำเนินการแก้ไขได้", + 'admin.plugins.perm.db:write:accommodations': + "สร้าง แก้ไข และลบที่พัก (ช่วงที่พัก) ในการเดินทางที่ผู้ใช้บริการสามารถแก้ไขได้", + 'admin.plugins.perm.db:write:daynotes': "สร้าง แก้ไข และลบบันทึกประจำวันของการเดินทางที่ผู้ใช้บริการสามารถแก้ไขได้", + 'admin.plugins.perm.db:meta': "แนบข้อมูลส่วนตัวของตัวเองไปกับการเดินทาง สถานที่ และวันที่ผู้ใช้บริการสามารถเข้าถึงได้", + 'admin.plugins.perm.ws:broadcast:trip': "ส่งการอัปเดตแบบเรียลไทม์ให้กับสมาชิกทริป", + 'admin.plugins.perm.ws:broadcast:user': "ส่งการอัปเดตแบบเรียลไทม์ไปยังผู้ใช้แต่ละราย", + 'admin.plugins.perm.hook:photo-provider': "มอบภาพถ่ายให้กับความทรงจำ", + 'admin.plugins.perm.hook:calendar-source': "จัดให้มีกิจกรรมในปฏิทิน", + 'admin.plugins.perm.hook:place-detail-provider': "เพิ่มรายละเอียด (บทวิจารณ์ คะแนน และลิงก์) ให้กับสถานที่", + 'admin.plugins.perm.hook:trip-warning-provider': "แจ้งเตือนการตรวจสอบความถูกต้องในการเดินทาง (แสดงใน Planner)", + 'admin.plugins.perm.hook:table-contributor': "เพิ่มคอลัมน์และการดำเนินการให้กับมุมมองการเดินทาง (การจอง สถานที่ วัน)", + 'admin.plugins.perm.hook:map-marker-provider': "เพิ่มเครื่องหมายลงในแผนที่การเดินทาง (เช่น แสดงการจองหรือ POI)", + 'admin.plugins.perm.hook:map-layer-provider': "วาดเส้นทาง ทางเดิน และโซนบนแผนที่การเดินทาง", + 'admin.plugins.perm.hook:route-provider': + "เสนอโปรไฟล์เส้นทางที่ผู้วางแผนสามารถกำหนดเส้นทางวันได้ (เช่น การกำหนดเส้นทาง EV พร้อมจุดชาร์จ)", + 'admin.plugins.perm.hook:day-schedule-provider': + "แนบรายการเวลาเข้ากับแผนวัน (จุดชาร์จ บัฟเฟอร์ความปลอดภัย)", + 'admin.plugins.perm.hook:day-tint-provider': + "กำหนดสีให้แต่ละวันในแผนรายวัน (เช่น เพื่อแสดงว่าวันนั้นอยู่ในช่วงใดของทริป)", + 'admin.plugins.cap.mcpTools': "เผยแพร่เครื่องมือ AI", + 'admin.plugins.mcpToolsTitle': "เครื่องมือ AI ที่เผยแพร่", + 'admin.plugins.mcpToolsHint': "ผู้ช่วยสามารถเรียกใช้สิ่งเหล่านี้ในนามของผู้ใช้ได้ แต่ละคนดำเนินการตามสิทธิ์การเข้าถึงที่ได้รับข้างต้น", + 'admin.plugins.perm.mcp:tools': + "เผยแพร่เครื่องมือที่ผู้ช่วย AI สามารถทำงานในนามของคุณ (จะกระทำกับการเข้าถึงที่คุณให้สิทธิ์ปลั๊กอินที่นี่ ไม่ใช่กับผู้ช่วยเอง)", + 'admin.plugins.perm.geolocation:read': + "ขอตำแหน่งปัจจุบันของคุณในขณะที่มุมมองใดมุมมองหนึ่งเปิดอยู่ (TREK อ่านภายใต้การอนุญาตตำแหน่งของไซต์นี้ ไม่ใช่ของปลั๊กอิน)", + 'admin.plugins.perm.hook:pdf-section-provider': "เพิ่มส่วนข้อความต่อท้ายการส่งออก PDF ของการเดินทาง", + 'admin.plugins.perm.hook:atlas-layer-provider': + "เน้นประเทศต่างๆ บนแผนที่โลก Atlas (เช่น สิ่งที่อยากได้หรือคำแนะนำการเดินทาง)", + 'admin.plugins.perm.hook:journal-entry-provider': "เพิ่มแถวพิเศษ (ลิงก์ สถิติ) ให้กับรายการบันทึกประจำวัน", + 'admin.plugins.perm.hook:trip-card-provider': "เพิ่มป้ายเล็กๆ (สถานะ จำนวน) ลงในการ์ดการเดินทางบนแดชบอร์ดของคุณ", + 'admin.plugins.perm.hook:notification-channel': "ส่งการแจ้งเตือนของคุณผ่านช่องทางเพิ่มเติม", + 'admin.plugins.perm.hook:user-data': + "ลบหรือส่งออกข้อมูลที่เก็บไว้เกี่ยวกับผู้ใช้ (การลบบัญชี GDPR และคำขอข้อมูล)", + 'admin.plugins.perm.events:subscribe': "ตอบสนองต่อเหตุการณ์กิจกรรมหลัก (ชื่องาน + ทริปเท่านั้น ไม่ใช่เนื้อหา)", + 'admin.plugins.perm.jobs:run': + "รันงานพื้นหลังที่ประกาศตามกำหนดเวลา (ไม่มีบริบทของผู้ใช้ — ไม่สามารถอ่านข้อมูลผู้ใช้ได้)", + 'admin.plugins.perm.http:outbound': "ส่งคำขอขาออกไปยังโฮสต์ที่ประกาศไว้", + 'admin.plugins.perm.db:read:collab': + "อ่านบันทึก โพล และข้อความแชทของทริปที่ผู้ใช้ที่กำลังดำเนินการเข้าถึงได้ (ต้องการส่วนเสริม Collab)", + 'admin.plugins.perm.db:read:files:content': "อ่านเนื้อหาไบต์ของไฟล์ในการเดินทางที่ผู้ใช้ที่ดำเนินการสามารถเข้าถึงได้", + 'admin.plugins.perm.db:create:trips': "สร้างการเดินทางใหม่ที่เป็นของผู้ใช้ที่รักษาการ", + 'admin.plugins.perm.rates:read': "อ่านอัตราแลกเปลี่ยนสกุลเงินแคชของโฮสต์", + 'admin.plugins.updateConsentTitle': "การอัปเดตนี้ต้องการสิทธิ์ใหม่", + 'admin.plugins.updateConsentBody': + "{name} v{version} กำลังขอสิทธิ์ที่คุณยังไม่ได้ให้ มีการติดตั้งเวอร์ชันใหม่แล้ว แต่จะยังคงปิดอยู่จนกว่าคุณจะอนุมัติ", + 'admin.plugins.updateNewPermissions': "สิทธิ์ที่ร้องขอใหม่", + 'admin.plugins.updateNewEgress': "การเชื่อมต่อขาออกใหม่", + 'admin.plugins.updateApprove': "อนุมัติและเปิดใช้งาน", + 'admin.plugins.updateLater': "ปิดไว้ก่อน", + 'admin.plugins.updateKeptOff': "ติดตั้งการอัปเดตแล้ว — ปล่อยทิ้งไว้จนกว่าคุณจะอนุมัติสิทธิ์ใหม่", + 'admin.plugins.reviewedMeaning': + "\"ตรวจสอบแล้ว\" หมายถึงผู้ดูแล TREK ได้สแกนปลั๊กอินนี้หามัลแวร์ในแต่ละเวอร์ชันเท่านั้น ไม่ได้ตรวจสอบคุณภาพหรือการทำงาน จึงไม่ใช่การรับประกันว่าปลั๊กอินจะปลอดภัย", + 'admin.plugins.security.title': "วิธีการบรรจุปลั๊กอิน — และข้อจำกัด", + 'admin.plugins.security.isolationTitle': "ปลั๊กอินทุกตัวทำงานแบบบรรจุกล่อง", + 'admin.plugins.security.isolationBody': + "ปลั๊กอินทำงานเป็นกระบวนการที่ล็อคไว้ซึ่งสามารถอ่านได้เฉพาะไฟล์ของตัวเองเท่านั้น ไม่สามารถอ่านฐานข้อมูล ข้อมูลลับในการเข้าสู่ระบบ หรือคีย์เข้ารหัสของคุณ ไม่สามารถเริ่มโปรแกรมอื่น และไม่สามารถเขียนไฟล์ได้ทุกที่ อินเทอร์เฟซทำงานในกรอบเบราว์เซอร์ที่ปิดสนิท ซึ่งไม่สามารถอ่านคุกกี้เซสชันของคุณหรือแตะหน้า TREK ที่อยู่รอบๆ ได้", + 'admin.plugins.security.permsTitle': "สิทธิ์หมายถึงอะไร", + 'admin.plugins.security.permsBody': + "การอนุญาตที่แสดงก่อนที่คุณจะติดตั้งเป็นขีดจำกัดที่ TREK บังคับใช้ในขณะที่ปลั๊กอินทำงาน — แท้จริงแล้วไม่สามารถทำอะไรก็ตามที่ไม่อยู่ในรายการได้ แต่พวกเขาจะบอกคุณว่าปลั๊กอินทำอะไรได้บ้าง ไม่ใช่ว่าจริงๆ แล้วปลั๊กอินทำอะไรได้บ้าง ปลั๊กอินที่อนุญาตให้อ่านการเดินทางของคุณและเข้าถึงเซิร์ฟเวอร์สามารถส่งการเดินทางของคุณไปยังเซิร์ฟเวอร์นั้นได้ ดังนั้นควรอ่านสิทธิ์และโฮสต์ขาออก ไม่ใช่แค่คำอธิบาย", + 'admin.plugins.security.limitsTitle': "สิ่งที่เราไม่สามารถสัญญาได้", + 'admin.plugins.security.limitsBody': + "การแยกออกจากกันถือเป็นขอบเขตซอฟต์แวร์ที่แข็งแกร่ง ไม่ใช่ขอบเขตที่สมบูรณ์ ปลั๊กอินทำงานตามสิทธิ์ที่คุณอนุมัติ ดังนั้นภายในสิทธิ์เหล่านั้น ปลั๊กอินจึงสามารถทำงานแตกต่างไปจากคำอธิบายที่แนะนำได้ และสามารถส่งข้อมูลที่เก็บไว้อย่างถูกต้องไปยังโฮสต์ที่ประกาศไว้ได้ TREK ไม่ได้อ่านหรือตัดสินว่าโค้ดของปลั๊กอินทำอะไรได้บ้าง", + 'admin.plugins.security.worstTitle': "กรณีที่เลวร้ายที่สุด", + 'admin.plugins.security.worstBody': + "ปลั๊กอินที่ไม่เป็นมิตรที่คุณเปิดอาจใช้ข้อมูลและการเชื่อมต่อที่คุณมอบให้ในทางที่ผิด เช่น ทำให้การเดินทางที่ได้รับอนุญาตให้อ่านรั่วไหล มันไม่สามารถขโมยรหัสผ่าน ปลอมล็อกอินของผู้ดูแลระบบ รันคำสั่งบนเซิร์ฟเวอร์ของคุณ หรือเข้าถึงข้อมูลที่คุณไม่ได้อนุญาต ความเสียหายจะยังคงอยู่ในสิ่งที่คุณอนุมัติ และการปิดปลั๊กอินจะหยุดความเสียหายนั้น", + 'admin.plugins.security.reviewedTitle': "“สอบทานแล้ว” หมายถึงอะไร", + 'admin.plugins.security.reviewedBody': + "ปลั๊กอินที่ได้รับการตรวจสอบได้รับการสแกนหามัลแวร์ด้วยตนเองโดยผู้ดูแล TREK ในแต่ละเวอร์ชัน — ตรวจสอบโค้ดที่ไม่เป็นมิตร ไม่ใช่เพื่อดูว่าทำงานได้ดีหรือไม่ ไม่ใช่คำสัญญาว่าปลั๊กอินจะไม่เป็นอันตราย", + 'admin.plugins.security.signedTitle': "\"ลงนาม\" หมายถึงอะไร", + 'admin.plugins.security.signedBody': + "การตรวจสอบผลรวม TREK จะตรวจสอบในทุกการติดตั้งเพื่อพิสูจน์ว่าไฟล์เป็นสิ่งที่รีจิสทรีรับรอง ลายเซ็นพิสูจน์บางสิ่งที่แตกต่าง: ลายเซ็นเหล่านี้มาจากผู้เขียน ลงนามด้วยกุญแจที่พวกเขาถือเท่านั้น ปลั๊กอินที่ลงนามมีทั้งสองอย่าง ปลั๊กอินที่ไม่ได้ลงนามนั้นไม่ปลอดภัย — เพียงแต่มีการรับประกันน้อยกว่าหนึ่งรายการ และปลั๊กอินส่วนใหญ่ในรีจิสทรีก็ยังไม่ได้ลงนามในปัจจุบัน", + 'admin.plugins.signed': "ลงนาม", + 'admin.plugins.signedHint': "ตรวจสอบกับรหัสลงนามของผู้เขียนเมื่อมีการติดตั้ง", + 'admin.plugins.unsigned': "ไม่ได้ลงนาม", + 'admin.plugins.unsignedHint': + "ไฟล์ตรงกับสิ่งที่รีจิสทรีรับรอง แต่ไม่มีสิ่งใดเชื่อมโยงกับผู้เขียน รับประกันน้อยกว่าหนึ่งข้อ — ไม่ปลอดภัย", + 'admin.plugins.updateBlocked': "การอัปเดตถูกบล็อก — {reason}", + 'admin.plugins.reviewBlock': "การตรวจสอบ", + 'admin.plugins.retrusted': "คีย์การลงนามใหม่ที่เชื่อถือได้ — ปลั๊กอินได้รับการอัปเดตแล้ว", + 'admin.plugins.sig.title': "ไม่สามารถยืนยันลายเซ็นของ {name} ได้", + 'admin.plugins.sig.keyChangedBody': + "รหัสการลงนามของผู้เขียนไม่ใช่รหัสเดียวกับที่ติดตั้งปลั๊กอินนี้ ผู้เขียนจะหมุนเวียนคีย์ — แต่ผู้โจมตีที่เข้ามาแทนที่ปลั๊กอินจะมีลักษณะเช่นนี้ทุกประการ", + 'admin.plugins.sig.invalidBody': + "ไฟล์ไม่ตรงกับลายเซ็นของผู้เขียน สิ่งเหล่านี้ไม่ใช่สิ่งที่ผู้เขียนลงนาม ไม่ว่าพวกเขาจะเสียหายหรือถูกดัดแปลงก็ตาม สิ่งนี้ไม่สามารถแทนที่ได้", + 'admin.plugins.sig.missingBody': + "ปลั๊กอินนี้ได้รับการลงนามเมื่อคุณติดตั้ง แต่เวอร์ชันใหม่ไม่มีลายเซ็น TREK จะไม่ยอมรับการปรับลดรุ่นอย่างเงียบๆ สิ่งนี้ไม่สามารถแทนที่ได้", + 'admin.plugins.sig.incompleteBody': + "รายการรีจิสทรีเป็นแบบ Half-Signed: จะประกาศคีย์ผู้เขียน แต่เวอร์ชันไม่มีลายเซ็น (หรือย้อนกลับ) นั่นเป็นข้อผิดพลาดด้านปลั๊กอิน สิ่งนี้ไม่สามารถแทนที่ได้", + 'admin.plugins.sig.pinnedKey': "คีย์ที่ใช้ติดตั้งปลั๊กอินนี้", + 'admin.plugins.sig.newKey': "ที่สำคัญมันกำลังนำเสนออยู่ในขณะนี้", + 'admin.plugins.sig.confirmOutOfBand': + "TREK ไม่สามารถบอกได้ว่าการหมุนเวียนคีย์ที่ถูกต้องตามกฎหมายนอกเหนือจากการครอบครอง — ทั้งสองดูเหมือนกันจากที่นี่ ยืนยันรหัสใหม่กับผู้เขียนผ่านช่องทางที่คุณเชื่อถือแล้วก่อนที่จะยอมรับ เมื่อคุณดำเนินการแล้ว ปลั๊กอินจะได้รับการอัปเดตและรหัสใหม่จะถูกจดจำ", + 'admin.plugins.sig.retrustConfirm': "เชื่อถือคีย์ใหม่และอัปเดต", + 'admin.plugins.sig.cancel': "อย่าวางใจมัน", + 'admin.plugins.sig.consentUnsigned': + "ไม่มีสิ่งใดที่เชื่อมโยงกับเวอร์ชันนี้กับผู้เขียน ไฟล์ต่างๆ ตรงกับรีจิสทรี แต่ไม่มีลายเซ็นผู้เขียน", + 'admin.plugins.security.trustTitle': "บรรทัดล่าง", + 'admin.plugins.security.trustBody': + "การติดตั้งปลั๊กอินก็เหมือนกับการติดตั้งแอปของบุคคลที่สาม เพียงเพิ่มโค้ดจากผู้เขียนที่คุณเชื่อถือเท่านั้น และหากมีข้อสงสัย ให้ตรวจสอบด้วยตนเองก่อน TREK จะไม่รับผิดชอบต่อปลั๊กอินของบุคคลที่สาม", + 'admin.plugins.runtimeOn': "รันไทม์เปิดอยู่", + 'admin.plugins.tabDiscover': "ค้นพบ", + 'admin.plugins.searchPlaceholder': "ค้นหาปลั๊กอิน...", + 'admin.plugins.filterType': "ประเภท", + 'admin.plugins.filterStatus': "สถานะ", + 'admin.plugins.sortBy': "จัดเรียง", + 'admin.plugins.allTypes': "ทุกประเภท", + 'admin.plugins.allStatuses': "ทั้งหมด", + 'admin.plugins.stateOff': "ปิด", + 'admin.plugins.filterUpdate': "อัปเดตพร้อมใช้งาน", + 'admin.plugins.sortName': "ชื่อ", + 'admin.plugins.sortRecent': "ปรับปรุงล่าสุด", + 'admin.plugins.sortUpdates': "ปรับปรุงก่อน", + 'admin.plugins.sortDownloads': "ดาวน์โหลดมากที่สุด", + 'admin.plugins.updatesAvailable': "{count} มีการอัปเดตสำหรับปลั๊กอินของคุณ", + 'admin.plugins.newerNeedsTrek': "v{version} ว่าง — ต้องการ TREK {range}", + 'admin.plugins.updateAll': "อัปเดตทั้งหมด", + 'admin.plugins.versionsTitle': "รุ่นต่างๆ", + 'admin.plugins.versionPickerTitle': "เปลี่ยนเวอร์ชัน — {name}", + 'admin.plugins.versionSwitch': "เปลี่ยนไปที่ {version}", + 'admin.plugins.versionNeedsTrek': "ต้องการ TREK {range}", + 'admin.plugins.changeVersion': "เปลี่ยนเวอร์ชัน...", + 'admin.plugins.noVersions': "ไม่พบเวอร์ชันที่เผยแพร่ในรีจิสทรี", + 'admin.plugins.downgradeTitle': "ย้อนกลับปลั๊กอินนี้หรือไม่", + 'admin.plugins.downgradeBody': "การเปลี่ยนจาก v{from} เป็น v{to}: ข้อมูลที่เขียนโดยเวอร์ชันที่ใหม่กว่าจะยังคงอยู่ และเวอร์ชันเก่าอาจไม่เข้าใจ", + 'admin.plugins.downgradeConfirm': "ย้อนกลับ", + 'admin.plugins.updatesHeld': "การอัปเดตหยุดชั่วคราวเมื่อ v{version}", + 'admin.plugins.resumeUpdates': "ดำเนินการอัปเดตต่อ", + 'admin.plugins.updatesResumed': "การอัปเดตดำเนินการต่อ", + 'admin.plugins.noMatchInstalled': "ไม่มีปลั๊กอินที่ติดตั้งตรงกับการค้นหาของคุณ", + 'admin.plugins.noMatchRegistry': "ไม่มีปลั๊กอินในรีจิสทรีที่ตรงกับการค้นหาของคุณ", + 'admin.plugins.restart': "รีสตาร์ท", + 'admin.plugins.restarted': "ปลั๊กอินเริ่มต้นใหม่แล้ว", + 'admin.plugins.instanceSettings': "การตั้งค่าอินสแตนซ์", + 'admin.plugins.settingsSaved': "บันทึกการตั้งค่าแล้ว", + 'admin.plugins.settingsSavedRestarted': "บันทึกการตั้งค่าแล้ว — รีสตาร์ทปลั๊กอินแล้ว", + 'admin.plugins.actions': "การดำเนินการ", + 'admin.plugins.actions.confirm': "ดำเนินการนี้หรือไม่?", + 'admin.plugins.actions.inactive': "เปิดใช้งานปลั๊กอินเพื่อดำเนินการต่างๆ", + 'admin.plugins.requiredMissing': "จำเป็นต้องมี \"{field}\"", + 'admin.plugins.cap.readsTrips': "อ่านการเดินทางของคุณ", + 'admin.plugins.cap.readsUsers': "อ่านโปรไฟล์พื้นฐาน", + 'admin.plugins.cap.readsCosts': "อ่านค่าใช้จ่ายของคุณ", + 'admin.plugins.cap.readsPacking': "อ่านรายการจัดกระเป๋า", + 'admin.plugins.cap.readsFiles': "อ่านไฟล์การเดินทาง", + 'admin.plugins.cap.writesCosts': "เพิ่มต้นทุน", + 'admin.plugins.cap.writesPlaces': "แก้ไขสถานที่", + 'admin.plugins.cap.writesDays': "แก้ไขวัน", + 'admin.plugins.cap.writesItinerary': "แก้ไขรายละเอียดการเดินทาง", + 'admin.plugins.cap.writesTrips': "แก้ไขการเดินทาง", + 'admin.plugins.cap.metadata': "เพิ่มข้อมูลเมตา", + 'admin.plugins.cap.widget': "วิดเจ็ตแดชบอร์ด", + 'admin.plugins.cap.heroWidget': "วิดเจ็ตบัตรผ่านขึ้นเครื่อง", + 'admin.plugins.cap.placeSlot': "รายละเอียดสถานที่", + 'admin.plugins.cap.daySlot': "รายละเอียดวัน", + 'admin.plugins.cap.reservationSlot': "รายละเอียดการจอง", + 'admin.plugins.cap.replacesTabs': "แทนที่แท็บวางแผน", + 'admin.plugins.cap.realtime': "การอัปเดตตามเวลาจริง", + 'admin.plugins.cap.notificationChannel': "ช่องทางการรับแจ้ง", + 'admin.plugins.cap.photos': "ให้บริการภาพถ่าย", + 'admin.plugins.cap.calendar': "จัดเตรียมกิจกรรมในปฏิทิน", + 'admin.plugins.cap.placeDetails': "เสริมสร้างสถานที่ต่างๆ", + 'admin.plugins.cap.warnings': "ปัญหาเรื่องแฟล็ก", + 'admin.plugins.cap.mapLayers': "วาดบนแผนที่", + 'admin.plugins.cap.routing': "เสนอเส้นทาง", + 'admin.plugins.cap.daySchedule': "เพิ่มเวลาตามแผน", + 'admin.plugins.cap.dayTint': "วันสีอ่อน", + 'admin.plugins.cap.geolocation': "อ่านตำแหน่งของคุณ", + 'admin.plugins.cap.events': "ตอบสนองต่อกิจกรรม", + 'admin.plugins.cap.requiresAddon': "ต้องใช้ {addon}", + 'admin.plugins.cap.dependsOn': "ต้องการ {id} {version}", + 'admin.plugins.dep.addonDisabledToast': "เปิดใช้งานส่วนเสริมที่จำเป็นก่อน: {addons}", + 'admin.plugins.dep.autoEnabled': "เปิดใช้งานปลั๊กอินที่จำเป็นก่อน: {plugins}", + 'admin.plugins.dep.downloaded': "ดาวน์โหลด {id} แล้ว", + 'admin.plugins.dep.resolveTitle': "ขาดการพึ่งพา", + 'admin.plugins.dep.resolveBody': "“{name}” จำเป็นต้องติดตั้งปลั๊กอินเหล่านี้ก่อนจึงจะสามารถเปิดใช้งานได้", + 'admin.plugins.dep.requires': "ต้องใช้ {version}", + 'admin.plugins.dep.mismatch': "ต้องการ {wanted} — {installed} ได้รับการติดตั้งแล้ว", + 'admin.plugins.dep.download': "ดาวน์โหลด", + 'admin.plugins.dep.update': "อัปเดต", + 'admin.plugins.dep.resolveHint': "ดาวน์โหลดเวอร์ชันล่าสุดที่เข้ากันได้ รวมถึงการขึ้นต่อกันของตัวเวอร์ชันเอง", + 'admin.plugins.dep.trekIncompatible': "ต้องการ TREK {range} — เซิร์ฟเวอร์นี้รัน {host}", + 'admin.plugins.dep.trekUnknown': "ไม่ได้บอกว่ารองรับ TREK เวอร์ชันใด", + 'admin.plugins.installCompatible': "ติดตั้ง {version}", + 'admin.plugins.installAnyway': "ติดตั้งต่อไป", + 'admin.plugins.rangeBypass.pill': "ตรวจสอบเวอร์ชันแล้ว", + 'admin.plugins.rangeBypass.pillHint': + "TREK_PLUGINS_IGNORE_TREK_RANGE ได้รับการตั้งค่าแล้ว - ปลั๊กอินอาจติดตั้งและทำงานนอกเวอร์ชัน TREK ที่ผู้เขียนประกาศไว้", + 'admin.plugins.rangeBypass.title': "ภายนอกเวอร์ชัน TREK ที่รองรับ", + 'admin.plugins.rangeBypass.noticeTitle': "ติดตั้งนอกเวอร์ชัน TREK ที่รองรับ", + 'admin.plugins.rangeBypass.body': + "“{name}” ประกาศรองรับ TREK {range} และเซิร์ฟเวอร์นี้รัน {host} TREK ปล่อยให้ผ่านไปได้เพียงเพราะตั้งค่า TREK_PLUGINS_IGNORE_TREK_RANGE แล้ว ผู้เขียนไม่ได้อัปเดตช่วงเวอร์ชันของปลั๊กอินสำหรับ TREK นี้ ดังนั้นจึงไม่มีการรับประกันว่าจะใช้งานได้ และในบางกรณีที่เกิดขึ้นไม่บ่อยนัก ปลั๊กอินที่ไม่ตรงกันอาจทำให้ข้อมูล TREK เสียหายได้ ดำเนินการต่อเฉพาะเมื่อคุณยอมรับความเสี่ยงนั้น", + 'admin.plugins.rangeBypass.bodyUnknown': + "“{name}” ไม่ได้ประกาศว่า TREK เวอร์ชันใดรองรับ เซิร์ฟเวอร์นี้รัน {host} TREK ปล่อยให้ผ่านไปได้เพียงเพราะตั้งค่า TREK_PLUGINS_IGNORE_TREK_RANGE แล้ว ไม่มีสิ่งใดบอกว่าผู้เขียนได้ทำการทดสอบบน TREK นี้ ดังนั้นจึงไม่มีการรับประกันว่าจะใช้งานได้ และในบางกรณีที่เกิดขึ้นไม่บ่อยนัก ปลั๊กอินที่ไม่ตรงกันอาจทำให้ข้อมูล TREK เสียหายได้ ดำเนินการต่อเฉพาะเมื่อคุณยอมรับความเสี่ยงนั้น", + 'admin.plugins.dep.trekBypassed': "อยู่นอกช่วง TREK ({range}) — เวอร์ชันถูกทำเครื่องหมายไว้", + 'admin.plugins.dep.trekBypassedUnknown': "ประกาศไม่มีช่วง TREK — เวอร์ชันถูกทำเครื่องหมายไว้", + 'admin.plugins.incompatible': "เข้ากันไม่ได้", + 'admin.plugins.accessTitle': "สิ่งที่สามารถเข้าถึงได้", + 'admin.plugins.connectsTitle': "เชื่อมต่อกับ", + 'admin.plugins.detailsTitle': "รายละเอียด", + 'admin.plugins.noAccess': "ไม่จำเป็นต้องเข้าถึงเป็นพิเศษ", + 'admin.plugins.metaVersion': "เวอร์ชัน", + 'admin.plugins.metaSize': "ขนาด", + 'admin.plugins.metaRequires': "ต้องใช้", + 'admin.plugins.metaReviewed': "ตรวจสอบเมื่อ", + 'admin.plugins.downloads': "ดาวน์โหลด", + 'admin.addons.title': "ส่วนเสริม", + 'admin.addons.subtitle': "เปิดหรือปิดใช้งานคุณสมบัติเพื่อปรับแต่งประสบการณ์ TREK ของคุณ", + 'admin.addons.catalog.packing.name': "รายการ", + 'admin.addons.catalog.packing.description': "บรรจุรายการและงานที่ต้องทำสำหรับการเดินทางของคุณ", + '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': "วันหยุด", + 'admin.addons.catalog.vacay.description': "นักวางแผนวันหยุดส่วนตัวพร้อมมุมมองปฏิทิน", + 'admin.addons.catalog.atlas.name': "แผนที่", + 'admin.addons.catalog.atlas.description': "แผนที่โลกพร้อมประเทศที่เยี่ยมชมและสถิติการเดินทาง", + 'admin.addons.catalog.collab.name': "ร่วมมือกัน", + 'admin.addons.catalog.collab.description': "บันทึก โพล แชท และข้อเสนอแนะในการวางแผนร่วมกัน", + 'admin.addons.catalog.memories.name': "ภาพถ่าย (อิมมิช)", + 'admin.addons.catalog.memories.description': "แบ่งปันภาพถ่ายการเดินทางผ่านอินสแตนซ์ Immich ของคุณ", + 'admin.addons.catalog.mcp.name': "เอ็มซีพี", + 'admin.addons.catalog.mcp.description': "Model Context Protocol สำหรับการบูรณาการผู้ช่วย AI", + 'admin.addons.subtitleBefore': "เปิดหรือปิดคุณสมบัติเพื่อปรับแต่งของคุณ ", + 'admin.addons.subtitleAfter': " ประสบการณ์", + 'admin.addons.catalog.naver_list_import.name': "การนำเข้ารายการ Naver", + 'admin.addons.catalog.naver_list_import.description': "นำเข้าสถานที่จากรายการ Naver Maps ที่แชร์", + 'admin.addons.catalog.airtrail.name': "แอร์เทรล", + 'admin.addons.catalog.airtrail.description': "ซิงค์เที่ยวบินจากอินสแตนซ์ AirTrail ของคุณ", + 'admin.addons.catalog.llm_parsing.name': "การแยกวิเคราะห์ AI", + 'admin.addons.catalog.llm_parsing.description': "อ่านการจองที่ parser ในตัวไม่สามารถทำได้ โดยใช้โมเดล AI ที่คุณเลือก", + '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': "ไม่สามารถอัปเดต addon", + 'admin.addons.group.count': "เปิดใช้งาน {enabled} จาก {total} แล้ว", + 'admin.addons.noAddons': "ไม่มีส่วนเสริมให้ใช้งาน", + 'admin.weather.title': "ข้อมูลสภาพอากาศ", + 'admin.weather.badge': "ตั้งแต่วันที่ 24 มีนาคม 2569", + 'admin.weather.description': + "TREK ใช้ Open-Meteo เป็นแหล่งข้อมูลสภาพอากาศ Open-Meteo เป็นบริการสภาพอากาศแบบโอเพ่นซอร์สฟรี โดยไม่ต้องใช้คีย์ API", + 'admin.weather.forecast': "พยากรณ์อากาศ 16 วัน", + 'admin.weather.forecastDesc': "5 วันก่อนหน้า (OpenWeatherMap)", + 'admin.weather.climate': "ข้อมูลสภาพภูมิอากาศในอดีต", + 'admin.weather.climateDesc': "ค่าเฉลี่ยจาก 85 ปีที่ผ่านมาสำหรับวันที่อยู่นอกเหนือการคาดการณ์ 16 วัน", + 'admin.weather.requests': "10,000 คำขอ / วัน", + 'admin.weather.requestsDesc': "ฟรี ไม่ต้องใช้คีย์ API", + 'admin.weather.locationHint': + "สภาพอากาศจะขึ้นอยู่กับสถานที่แรกพร้อมพิกัดในแต่ละวัน หากไม่มีการกำหนดสถานที่ในหนึ่งวัน สถานที่ใดๆ จากรายการสถานที่จะถูกนำมาใช้เป็นข้อมูลอ้างอิง", + 'admin.tabs.mcpTokens': "การเข้าถึง MCP", + 'admin.mcpTokens.title': "การเข้าถึง MCP", + 'admin.mcpTokens.subtitle': "จัดการเซสชัน OAuth และโทเค็น 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': "ไอพี", + '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.nonDockerText': + "อินสแตนซ์ TREK นี้ไม่ได้ทำงานใน Docker หากต้องการอัปเดตเป็น {version} ให้เรียกใช้วิธีการติดตั้งหรืออัปเดตที่คุณใช้อีกครั้ง ตัวอย่างเช่น บน Proxmox Community Scripts ให้เรียกใช้การอัปเดตจากคอนโซล LXC:", + 'admin.update.wikiLink': "เปิดคู่มือการอัพเดต", + 'admin.update.reloadHint': "โปรดโหลดหน้านี้ใหม่ภายในไม่กี่วินาที", + 'admin.tabs.permissions': "สิทธิ์", + 'admin.addons.catalog.journey.name': "การเดินทาง", + 'admin.addons.catalog.journey.description': + "ติดตามการเดินทางและบันทึกการเดินทางพร้อมการเช็คอิน รูปภาพ และเรื่องราวประจำวัน", + 'admin.addons.catalog.collections.name': "คอลเลกชัน", + 'admin.addons.catalog.collections.description': "รวบรวมสถานที่จากการเดินทางใดๆ ลงในรายการที่มีชื่อและนำกลับมาใช้ใหม่", + 'admin.passkey.title': "รหัสผ่านเข้าสู่ระบบ", + 'admin.passkey.cardHint': "อนุญาตให้ผู้ใช้ลงชื่อเข้าใช้ด้วยรหัสผ่าน (WebAuthn) ปิดโดยค่าเริ่มต้น", + 'admin.passkey.login': "เปิดใช้งานรหัสผ่านเข้าสู่ระบบ", + 'admin.passkey.loginHint': "แสดงตัวเลือก \"ลงชื่อเข้าใช้ด้วยรหัสผ่าน\" และให้ผู้ใช้ลงทะเบียนรหัสผ่านในการตั้งค่าของตน", + 'admin.passkey.notConfigured': + "ยังไม่มีการแก้ไขโดเมน WebAuthn สำหรับการปรับใช้นี้ ตั้งค่า APP_URL หรือ Relying Party ID ด้านล่าง — พาสคีย์จะถูกซ่อนไว้จนกว่าจะถึงเวลานั้น", + 'admin.passkey.rpId': "Relying Party ID (โดเมน)", + 'admin.passkey.rpIdHint': + "พาสคีย์โดเมนเปล่าถูกผูกไว้กับ เช่น trek.example.org เว้นว่างไว้เพื่อรับข้อมูลจาก APP_URL การเปลี่ยนแปลงในภายหลังจะทำให้พาสคีย์ที่มีอยู่เป็นโมฆะ", + 'admin.passkey.origins': "ต้นกำเนิดที่ได้รับอนุญาต", + 'admin.passkey.originsHint': + "ต้นทางแบบเต็มที่คั่นด้วยเครื่องหมายจุลภาค เช่น https://trek.example.org. เว้นว่างไว้เพื่อใช้ APP_URL", + 'admin.passkey.reset': "รีเซ็ตพาสคีย์", + 'admin.passkey.resetHint': + "ลบพาสคีย์ของผู้ใช้รายนี้ทั้งหมด (เช่น บนอุปกรณ์ที่สูญหาย) พวกเขายังสามารถลงชื่อเข้าใช้ด้วยรหัสผ่านได้", + 'admin.passkey.resetConfirm': "ลบรหัสผ่านทั้งหมดสำหรับ {name} หรือไม่", + 'admin.passkey.resetDone': "ลบรหัสผ่าน {count} รายการแล้ว", + 'admin.group.users': "ผู้ใช้", + 'admin.group.config': "การกำหนดค่า", + 'admin.group.integration': "การเชื่อมต่อ", + 'admin.group.maintenance': "การบำรุงรักษา", + 'admin.invite.tripLabel': "เพิ่มในการเดินทาง (ไม่บังคับ)", + 'admin.invite.tripNone': "ไม่มีการเดินทาง", + 'admin.invite.tripHint': "ผู้ใช้ใหม่จะถูกเพิ่มในการเดินทางนี้โดยอัตโนมัติเมื่อลงทะเบียนผ่านลิงก์", + 'admin.invite.boundTo': "เพิ่มใน {trip}", + 'admin.trekApi.badgeDefault': "ค่าเริ่มต้นที่แนะนำ", + 'admin.googleCaveat.badge': "ไม่แนะนำ", + 'admin.googleCaveat.body': "TREK เป็นโอเพนซอร์ส และเราไม่ได้วางตัวเป็นกลางในเรื่องนี้ คะแนนและรูปภาพของธุรกิจทั่วไปในระดับนี้มีอยู่ที่ Google เท่านั้น ซึ่งก็คือการผูกขาด ช่องนี้มีไว้เพราะไม่มีทางเลือก ไม่ใช่เพราะเราแนะนำ ทุกการค้นหาจะส่งไปยัง Google", + 'admin.trekApi.tagline': "ดัชนีสถานที่ของ TREK เอง ค้นหาได้โดยไม่ต้องมีคีย์ Google ไม่มีโควตา และไม่มีใครนับจำนวนการค้นหาของคุณ", + 'admin.trekApi.factPlaces': "73.6 ล้านสถานที่ทั่วโลก", + 'admin.trekApi.factNoKey': "ไม่ต้องมีคีย์ ไม่มีโควตา", + 'admin.trekApi.factOffline': "แพ็กเกจประเทศใช้งานแบบออฟไลน์ได้", + 'admin.trekApi.factPrivacy': "จะไม่บันทึกการค้นหา", + 'admin.trekApi.more': "มีอะไรบ้าง", + 'admin.trekApi.fieldPhone': "โทรศัพท์", + 'admin.trekApi.fieldStableId': "รหัสประจำที่คงที่", + 'admin.trekApi.includedNote': "คำอธิบายมาจากเว็บไซต์ของสถานที่นั้นเอง และเวลาเปิดทำการมาจาก OpenStreetMap เมื่อมีการระบุไว้", + 'admin.trekApi.notRatings': "คะแนน", + 'admin.trekApi.notPhotos': "รูปภาพของธุรกิจทั่วไป", + 'admin.trekApi.notIncludedNote': "ไม่มีชุดข้อมูลเปิดใดมีข้อมูลทั้งสองอย่างนี้ ไม่ว่าจะราคาเท่าใด คีย์ Google จึงยังเป็นทางเดียวสำหรับข้อมูลทั้งสอง", + 'admin.trekApi.sourcesLabel': "แหล่งข้อมูล", + 'admin.trekApi.sourcesNote': "ทุกฟิลด์ในคำตอบจะระบุว่ามาจากแหล่งใด", + 'admin.trekApi.included': "รวมอยู่", + 'admin.trekApi.notIncluded': "ไม่รวมอยู่", + 'admin.amapKey': "คีย์ API ของ Amap (高德地图)", + 'admin.amapKeyHint': "สำหรับค้นหาสถานที่ในจีนแผ่นดินใหญ่ที่ Google ใช้ไม่ได้และ OpenStreetMap ครอบคลุมไม่มาก ต้องใช้คีย์ “Web 服务” (เว็บเซอร์วิส) ไม่ใช่คีย์ JS API รับได้ที่ console.amap.com", + 'admin.placesProvider.title': "ผู้ให้บริการค้นหาสถานที่", + 'admin.placesProvider.subtitle': "ดัชนีของ TREK และ OpenStreetMap ตอบทุกการค้นหา การตั้งค่านี้เลือกผู้ให้บริการอื่นที่จะถามเมื่อไม่พบข้อมูล: อัตโนมัติจะเลือก Google หากมีคีย์ แล้วจึง Amap", + 'admin.placesProvider.auto': "อัตโนมัติ", + 'admin.placesProvider.google': "Google Places", + 'admin.placesProvider.amap': "Amap (高德地图)", + 'admin.placesProvider.openstreetmap': "OpenStreetMap", + 'admin.placesProvider.missingKey': "ผู้ให้บริการที่เลือกยังไม่ได้ตั้งค่าคีย์ API ดังนั้นการค้นหาสถานที่จะใช้เพียงดัชนี TREK และ OpenStreetMap", + 'admin.placesProvider.saved': "บันทึกผู้ให้บริการค้นหาสถานที่แล้ว", + 'admin.googleOptions': "สิ่งที่คีย์นี้ใช้ได้", + 'admin.googleOptionsSummary': "เปิด {on} จาก {total}", + 'admin.transitProvider.title': "ผู้ให้บริการขนส่งสาธารณะ", + 'admin.transitProvider.subtitle': "บริการใดจะตอบการค้นหาการขนส่งสาธารณะ", + 'admin.transitProvider.transitous': "Transitous (ฟรี)", + 'admin.transitProvider.google': "Google", + 'admin.transitProvider.transitousHint': "ฟีด GTFS จากชุมชน ฟรีและไม่ต้องใช้คีย์ โดยครอบคลุมยุโรปได้ดีที่สุด", + 'admin.transitProvider.googleHint': "ใช้คีย์ Google API ด้านบนสำหรับภูมิภาคที่ Transitous ไม่มีข้อมูล คิดค่าบริการต่อการค้นหา — จะใช้ Transitous เมื่อยังไม่ได้ตั้งค่าคีย์", + 'admin.transitProvider.noKeyWarning': "เลือก Google แล้ว แต่ยังไม่ได้ตั้งค่าคีย์ Google API — การค้นหาการขนส่งยังใช้ Transitous อยู่ เพิ่มคีย์ในส่วนคีย์ API ด้านบน", + 'admin.transitProvider.personalKeyWarning': "ตั้งค่าเฉพาะคีย์ Google ของคุณเอง จึงทำให้การค้นหาของสมาชิกคนอื่นยังกลับไปใช้ Transitous บันทึกคีย์ด้านบนในฐานะผู้ดูแลเพื่อใช้กับทั้งอินสแตนซ์", + 'admin.placeShadow.title': "บันทึกการค้นหาสถานที่", + 'admin.placeShadow.subtitle': "บันทึกผลค้นหาที่ถูกเลือก เพื่อวัดดัชนีสถานที่อื่นกับการค้นหาจริงในอนาคต ข้อมูลจะไม่ออกจากอินสแตนซ์นี้ และผู้ดูแลส่งออกหรือลบบันทึกได้ทุกเมื่อ", + 'admin.plugins.cap.search': "ตอบการค้นหา", + 'admin.addons.catalog.roadtrip.name': "โรดทริป", + 'admin.addons.catalog.roadtrip.description': "วางแผนการขับรถด้วยจุดแวะตามเส้นทาง เวลาเดินทาง และเวลาไปถึงที่อัปเดตเอง", + 'admin.addons.catalog.dawarich.name': "Dawarich", + 'admin.addons.catalog.dawarich.description': "อ่านการเยี่ยมชมและเส้นทางที่บันทึกจากอินสแตนซ์ Dawarich ที่ผู้อ่านแต่ละคนเชื่อมต่อเอง", + 'admin.placesUsageTitle': "คีย์นี้ใช้ทำอะไร", + 'admin.mapsKeyHintShort': "เพิ่มรูปภาพ คะแนน และเวลาเปิดทำการ ทุกการค้นหาจะส่งไปยัง Google", + 'admin.amapKeyHintShort': "สำหรับค้นหาสถานที่ในจีนแผ่นดินใหญ่ ต้องใช้คีย์เว็บเซอร์วิส ไม่ใช่คีย์ JS API", +}; +export default admin; diff --git a/shared/src/i18n/th/airport.ts b/shared/src/i18n/th/airport.ts new file mode 100644 index 000000000..cd04d6049 --- /dev/null +++ b/shared/src/i18n/th/airport.ts @@ -0,0 +1,6 @@ +import type { TranslationStrings } from '../types'; + +const airport: TranslationStrings = { + 'airport.searchPlaceholder': "รหัสสนามบินหรือเมือง (เช่น FRA)", +}; +export default airport; diff --git a/shared/src/i18n/th/atlas.ts b/shared/src/i18n/th/atlas.ts new file mode 100644 index 000000000..c99a40345 --- /dev/null +++ b/shared/src/i18n/th/atlas.ts @@ -0,0 +1,65 @@ +import type { TranslationStrings } from '../types'; + +const atlas: TranslationStrings = { + '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.searchPlaces': "สถานที่", + 'atlas.bucketNamePlaceholder': "ชื่อ (ประเทศ เมือง สถานที่...)", + 'atlas.month': "เดือน", + 'atlas.year': "ปี", + 'atlas.addToBucketHint': "บันทึกเป็นสถานที่ที่คุณต้องการเยี่ยมชม", + 'atlas.removeFromBucket': "ลบออกจากสิ่งที่อยากได้", + 'atlas.removeFromBucketHint': "นำประเทศนี้ออกจากรายการสิ่งที่คุณอยากทำ", + 'atlas.bucketWhen': "คุณวางแผนที่จะเยี่ยมชมเมื่อไหร่?", + 'atlas.bucketDuplicate': "มีอยู่ในรายการสถานที่อยากไปแล้ว", + 'atlas.statsTab': "สถิติ", + 'atlas.bucketTab': "สถานที่อยากไป", + 'atlas.addBucket': "เพิ่มในรายการสถานที่อยากไป", + 'atlas.bucketNotesPlaceholder': "หมายเหตุ (ไม่บังคับ)", + 'atlas.bucketEmpty': "รายการสถานที่อยากไปของคุณว่างเปล่า", + 'atlas.bucketEmptyHint': "เพิ่มสถานที่ที่คุณใฝ่ฝันอยากจะไปเยี่ยมชม", + 'atlas.days': "วัน", + 'atlas.visitedCountries': "ประเทศที่มาเยือน", + 'atlas.cities': "เมือง", + 'atlas.noData': "ยังไม่มีข้อมูลการเดินทาง", + 'atlas.noDataHint': "สร้างการเดินทางและเพิ่มสถานที่เพื่อดูแผนที่โลกของคุณ", + '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.tripSingular': "การเดินทาง", + 'atlas.tripPlural': "ทริป", + 'atlas.placeVisited': "สถานที่ที่เยี่ยมชม", + 'atlas.placesVisited': "สถานที่เยี่ยมชม", + 'atlas.planned': "วางแผนแล้ว", + 'atlas.showPlanned': "แสดงประเทศที่วางแผนไว้", + 'atlas.plannedFor': "วางแผนไว้สำหรับ", + 'atlas.antarctica': "แอนตาร์กติกา", + 'atlas.lastVisitLabel': "ทริปล่าสุด", +}; +export default atlas; diff --git a/shared/src/i18n/th/backup.ts b/shared/src/i18n/th/backup.ts new file mode 100644 index 000000000..19e9bff35 --- /dev/null +++ b/shared/src/i18n/th/backup.ts @@ -0,0 +1,72 @@ +import type { TranslationStrings } from '../types'; + +const backup: TranslationStrings = { + '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': "นักเทียบท่า", + 'backup.auto.envLockedHint': + "การสำรองข้อมูลอัตโนมัติได้รับการกำหนดค่าผ่านตัวแปรสภาพแวดล้อม Docker หากต้องการเปลี่ยนการตั้งค่าเหล่านี้ ให้อัปเดต docker-compose.yml และรีสตาร์ทคอนเทนเนอร์", + 'backup.auto.copyEnv': "คัดลอก Docker env vars", + 'backup.auto.envCopied': "คัดลอก Docker env vars ไปยังคลิปบอร์ดแล้ว", + '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': "เก็บไว้ตลอดไป", + 'backup.restoreConfirmTitle': "คืนค่าการสำรองข้อมูลหรือไม่", + 'backup.restoreWarning': + "ข้อมูลปัจจุบันทั้งหมด (การเดินทาง สถานที่ ผู้ใช้ การอัปโหลด) จะถูกแทนที่ด้วยข้อมูลสำรองอย่างถาวร การดำเนินการนี้ไม่สามารถยกเลิกได้", + 'backup.restoreTip': "เคล็ดลับ: สร้างการสำรองข้อมูลสถานะปัจจุบันก่อนที่จะกู้คืน", + 'backup.restoreConfirm': "ใช่ คืนค่า", +}; +export default backup; diff --git a/shared/src/i18n/th/budget.ts b/shared/src/i18n/th/budget.ts new file mode 100644 index 000000000..058467625 --- /dev/null +++ b/shared/src/i18n/th/budget.ts @@ -0,0 +1,163 @@ +import type { TranslationStrings } from '../types'; + +const budget: TranslationStrings = { + 'costs.confirm.deleteTitle': "ลบค่าใช้จ่ายใช่ไหม", + 'costs.confirm.deleteBody': "\"{name}\" จะถูกลบอย่างถาวร", + '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': "ต่อคน", + 'budget.table.perDay': "ต่อวัน", + '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': "คุณแน่ใจหรือไม่ว่าต้องการลบหมวดหมู่ \"{name}\" ที่มีรายการ {count}", + 'budget.deleteCategory': "ลบหมวดหมู่", + 'budget.perPerson': "ต่อคน", + 'budget.paid': "ชำระเงินแล้ว", + 'budget.open': "เปิด", + 'budget.noMembers': "ไม่มีสมาชิกที่ได้รับมอบหมาย", + 'budget.settlement': "การชำระบัญชี", + 'budget.settlementInfo': + "คลิกรูปประจำตัวของสมาชิกในรายการงบประมาณเพื่อทำเครื่องหมายเป็นสีเขียว ซึ่งหมายความว่าพวกเขาชำระเงินแล้ว ข้อตกลงจะแสดงให้เห็นว่าใครเป็นหนี้ใครและเป็นจำนวนเงินเท่าใด", + 'budget.netBalances': "ยอดคงเหลือสุทธิ", + 'budget.categoriesLabel': "หมวดหมู่", + 'costs.you': "คุณ", + 'costs.youShort': "ย", + 'costs.youLower': "คุณ", + 'costs.youOwe': "คุณเป็นหนี้", + 'costs.youOweSub': "คุณควรจะจ่ายเงินให้คนอื่น", + 'costs.youreOwed': "มีคนเป็นหนี้คุณ", + 'costs.youreOwedSub': "คนอื่นควรจ่ายเงินให้คุณ", + 'costs.totalSpend': "ค่าใช้จ่ายในการเดินทางทั้งหมด", + 'costs.totalSpendSub': "ทั่วทุกนักเดินทาง", + 'costs.to': "ถึง", + 'costs.from': "จาก", + 'costs.allSettled': "ทุกคนเคลียร์ยอดแล้ว", + 'costs.nothingOwed': "ไม่มีอะไรเป็นหนี้คุณ", + 'costs.yourShare': "ส่วนแบ่งของคุณ", + 'costs.youPaid': "คุณจ่ายเงินแล้ว", + 'costs.outstanding': "ยอดค้างชำระ", + 'costs.outstandingSub': "ค่าใช้จ่ายที่ยังไม่มีผู้ชำระเงิน", + 'costs.outstandingItems': "ค่าใช้จ่ายจำเป็นต้องมีผู้ชำระเงิน", + 'costs.expenses': "ค่าใช้จ่าย", + 'costs.entries': "{count} รายการ", + 'costs.searchPlaceholder': "ค้นหาค่าใช้จ่าย...", + 'costs.filter.all': "ทั้งหมด", + 'costs.filter.mine': "ชำระเงินโดยฉัน", + 'costs.filter.owed': "ฉันเป็นหนี้", + 'costs.filter.allCategories': "ทุกหมวดหมู่", + 'costs.filter.allDays': "ทั้งวัน", + 'costs.expensesCount': "{count} ค่าใช้จ่าย", + 'costs.addExpense': "เพิ่มค่าใช้จ่าย", + 'costs.editExpense': "แก้ไขค่าใช้จ่าย", + 'costs.noMatch': "ไม่มีค่าใช้จ่ายที่ตรงกับการค้นหาของคุณ", + 'costs.emptyText': "ไม่มีค่าใช้จ่ายเลย เพิ่มอันแรกของคุณ", + 'costs.spent': "{amount} ใช้จ่ายไป", + 'costs.noDate': "ไม่มีวันที่", + 'costs.noOnePaid': "ยังไม่มีใครจ่ายเงินเลย", + 'costs.youLent': "คุณให้ยืม {amount}", + 'costs.youBorrowed': "คุณยืม {amount}", + 'costs.settleUp': "เคลียร์ยอด", + 'costs.history': "ประวัติ", + 'costs.everyoneSquare': "ทุกคนเคลียร์ยอดแล้ว", + 'costs.nothingOutstanding': "ไม่มียอดค้างชำระในขณะนี้", + 'costs.pay': "จ่าย", + 'costs.pays': "จ่าย", + 'costs.settle': "ชำระ", + 'costs.balances': "ยอดคงเหลือ", + 'costs.byCategory': "ตามหมวดหมู่", + 'costs.noCategories': "ไม่มีค่าใช้จ่ายเลย", + 'costs.settleHistory': "ประวัติการชำระบัญชี", + 'costs.noSettlements': "ยังไม่มีการชำระเงิน", + 'costs.paymentsSettled': "{count} ชำระเงินเรียบร้อยแล้ว", + 'costs.paid': "จ่ายแล้ว", + 'costs.undo': "เลิกทำ", + 'costs.whatFor': "มันมีไว้เพื่ออะไร?", + 'costs.namePlaceholder': "เช่น อาหารเย็น ของที่ระลึก น้ำมัน…", + 'costs.note': "หมายเหตุ", + 'costs.notePlaceholder': "คุ้มครองอะไร ใครเป็นหนี้อะไรคืน...", + 'costs.addNote': "เพิ่มบันทึก", + 'costs.showNote': "แสดงบันทึก", + 'costs.hideNote': "ซ่อนบันทึก", + 'costs.totalAmount': "จำนวนเงินทั้งหมด", + 'costs.currency': "สกุลเงิน", + 'costs.day': "วัน", + 'costs.rateLabel': "1 {from} = {to}", + 'costs.category': "หมวดหมู่", + 'costs.whoPaid': "ใครเป็นคนจ่าย?", + 'costs.multiplePayers': "จ่ายหลายคนแล้ว", + 'costs.singlePayer': "คนหนึ่งจ่าย", + 'costs.payersUnbalanced': "จำนวนเงินของผู้ชำระจะต้องรวมกันไม่เกิน {amount}", + 'costs.splitBetween': "แบ่งเท่าๆ กันระหว่าง", + 'costs.split': "แยก", + 'costs.splitEqually': "เท่าๆ กัน", + 'costs.splitCustom': "กำหนดเอง", + 'costs.splitTicket': "ตั๋ว", + 'costs.pickSomeone': "เลือกอย่างน้อยหนึ่งคนที่จะแยกด้วย", + 'costs.splitSummary': "แยก {count} วิธี · {amount} วิธีละ", + 'costs.cat.accommodation': "ที่พัก", + 'costs.cat.food': "อาหารและเครื่องดื่ม", + 'costs.cat.groceries': "ร้านขายของชำ", + 'costs.cat.transport': "ขนส่ง", + 'costs.cat.flights': "เที่ยวบิน", + 'costs.cat.activities': "กิจกรรม", + 'costs.cat.sightseeing': "เที่ยวชมสถานที่", + 'costs.cat.shopping': "ช้อปปิ้ง", + 'costs.cat.fees': "ค่าธรรมเนียมและตั๋ว", + 'costs.cat.health': "สุขภาพ", + 'costs.cat.tips': "เคล็ดลับ", + 'costs.cat.fuel': "เชื้อเพลิง", + 'costs.cat.parking': "ที่จอดรถ", + 'costs.cat.other': "อื่นๆ", + 'costs.daysCount': "{count} วัน", + 'costs.travelers': "นักเดินทาง {count}", + 'costs.liveRate': "อัตราสด", + 'costs.settleAll': "ชำระทั้งหมด", + 'costs.payment': "การชำระเงิน", + 'costs.editPayment': "แก้ไขการชำระเงิน", + 'costs.addPayment': "เพิ่มการชำระเงิน", + 'costs.unfinished': "ยังไม่เสร็จ", + 'costs.unfinishedHint': "รวมเท่านั้น — ยังไม่ตัดสิน", + 'costs.tapToInclude': "แตะเพื่อรวม", + 'costs.amount': "จำนวน", + 'costs.ticketItemName': "ชื่อรายการ", + 'costs.ticketSplitting': "แยก:", + 'costs.ticketAddItem': "เพิ่มรายการ", + 'costs.ticketShares': "ส่วนแบ่งแต่ละคน", + 'costs.excluded': "ไม่รวม", + 'costs.splitBalanced': "หารเท่า ๆ กัน", + 'costs.splitSumUnder': "ผลรวมของการแยก: {sum} จาก {total} (ต่ำกว่าโดย {diff})", + 'costs.splitSumOver': "ผลรวมของการแยก: {sum} จาก {total} (มากกว่า {diff})", + 'costs.toggleSign': "สลับระหว่างค่าใช้จ่ายและการคืนเงิน", + 'costs.finalBudget': "งบประมาณสุดท้าย", + 'costs.finalExpenses': "ค่าใช้จ่ายที่ชำระแล้ว", + 'costs.finalReimbursed': "ยอดชดเชยสุทธิ", + 'costs.finalPending': "ยอดชดเชยที่รอดำเนินการ", + 'costs.receipts': "ใบเสร็จ", + 'costs.receiptsTitle': "ใบเสร็จและใบแจ้งหนี้", + 'costs.attachReceipt': "แนบใบเสร็จ / ใบแจ้งหนี้", + 'costs.noReceipts': "ยังไม่มีใบเสร็จแนบ", + 'costs.deleteReceipt': "ลบใบเสร็จ", + 'costs.viewReceipt': "ดูใบเสร็จ", + 'costs.receiptLeftBehind': "บันทึกไม่สำเร็จ และยังมีใบเสร็จที่อัปโหลด {count} รายการอยู่ ลบได้ในแท็บไฟล์", +}; + +export default budget; diff --git a/shared/src/i18n/th/categories.ts b/shared/src/i18n/th/categories.ts new file mode 100644 index 000000000..83324418e --- /dev/null +++ b/shared/src/i18n/th/categories.ts @@ -0,0 +1,25 @@ +import type { TranslationStrings } from '../types'; + +const categories: TranslationStrings = { + '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': "ลบไม่สำเร็จ", +}; +export default categories; diff --git a/shared/src/i18n/th/collab.ts b/shared/src/i18n/th/collab.ts new file mode 100644 index 000000000..4e11a00ad --- /dev/null +++ b/shared/src/i18n/th/collab.ts @@ -0,0 +1,97 @@ +import type { TranslationStrings } from '../types'; + +const collab: TranslationStrings = { + 'collab.chat.readOnly': "เข้าถึงการแชทนี้แบบอ่านอย่างเดียว", + 'collab.chat.messageOptions': "ตัวเลือกข้อความ", + 'collab.polls.confirmDeleteTitle': "ลบการสำรวจความคิดเห็นใช่ไหม", + 'collab.polls.confirmDeleteBody': "แบบสำรวจนี้จะถูกลบอย่างถาวร", + 'collab.polls.countdownDaysHours': "{d}d {h} เหลืออีก", + 'collab.polls.countdownHoursMinutes': "{h}ชม {m}นาทีที่เหลือ", + 'collab.polls.countdownMinutes': "เหลืออีก {m} นาที", + 'collab.polls.clearDeadline': "ล้างกำหนดเวลา", + '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.content': "เนื้อหา", + 'collab.notes.removeFile': "ลบ {name}", + '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.confirmDeleteTitle': "ลบบันทึกใช่ไหม", + 'collab.notes.confirmDeleteBody': "บันทึกนี้จะถูกลบอย่างถาวร", + 'collab.notes.pin': "พิน", + 'collab.notes.unpin': "เลิกปักหมุด", + 'collab.notes.daysAgo': "{n}d ที่แล้ว", + '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.markdownHint': "รองรับมาร์กดาวน์", + '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': "ปิดแล้ว", + 'collab.tabs.links': "ลิงก์", + 'collab.links.add': "เพิ่มลิงก์", + 'collab.chat.imageRejected': "อนุญาตเฉพาะรูป JPEG, PNG, GIF และ WebP ขนาดไม่เกิน 10 MB", + 'collab.links.cancel': "ยกเลิก", + 'collab.links.save': "บันทึกลิงก์", + 'collab.links.titlePlaceholder': "ชื่อลิงก์", + 'collab.links.urlPlaceholder': "https://...", + 'collab.links.empty': "ยังไม่มีลิงก์ที่แชร์", + 'collab.links.pin': "ปักหมุดลิงก์", + 'collab.links.unpin': "เลิกปักหมุดลิงก์", + 'collab.links.delete': "ลบลิงก์", +}; +export default collab; diff --git a/shared/src/i18n/th/collection.ts b/shared/src/i18n/th/collection.ts new file mode 100644 index 000000000..a1fca920e --- /dev/null +++ b/shared/src/i18n/th/collection.ts @@ -0,0 +1,207 @@ +import type { TranslationStrings } from '../types'; + +const collection: TranslationStrings = { + 'collections.saveNToList': "บันทึก {count} ลงในรายการ", + 'collections.addedNToList': "บันทึก {count} ไปที่ {name} แล้ว", + 'collections.noOwnLists': "คุณยังไม่มีรายการ", + 'collections.saveToListHint': "รายการที่ซ้ำกันจะถูกข้ามโดยอัตโนมัติ", + 'collections.role.label': "บทบาท", + 'collections.role.viewer': "ผู้ดู", + 'collections.role.editor': "บรรณาธิการ", + 'collections.role.admin': "ผู้ดูแลระบบ", + 'collections.picker.allLists': "รายการทั้งหมด", + 'collections.select': "เลือก", + 'collections.selectAll': "เลือกทั้งหมด", + 'collections.deselectAll': "ยกเลิกการเลือกทั้งหมด", + 'collections.moveToList': "ย้ายไปที่รายการ", + 'collections.duplicateToList': "ทำซ้ำในรายการ", + 'collections.moveToListTitle': "ย้าย {count} ไปยังรายการอื่น", + 'collections.duplicateToListTitle': "ทำซ้ำ {count} ไปยังรายการอื่น", + 'collections.noOtherLists': "ยังไม่มีรายการอื่นเลย", + 'collections.movedCount': "ย้ายสถานที่ {count} แห่ง", + 'collections.duplicatedCount': "ทำซ้ำสถานที่ {count} แห่ง", + 'collections.placeCount': "{count} สถานที่", + 'collections.category': "หมวดหมู่", + 'collections.noCategory': "ไม่มีหมวดหมู่", + 'collections.editListTitle': "แก้ไขรายการ", + 'collections.coverImage': "ภาพปก", + 'collections.addCover': "เพิ่มปก", + 'collections.changeCover': "เปลี่ยนปก", + 'collections.description': "คำอธิบาย", + 'collections.descriptionPlaceholder': "เพิ่มคำอธิบาย...", + 'collections.links': "ลิงก์", + 'collections.linkLabel': "ป้ายกำกับ", + 'collections.addLink': "เพิ่มลิงก์", + 'collections.addDetails': "เพิ่มรายละเอียด", + 'collections.addPlace': "เพิ่มสถานที่", + 'collections.addPlaceSearch': "ค้นหาสถานที่...", + 'collections.addPlaceHint': "ค้นหาเพื่อเพิ่มสถานที่ลงในรายการนี้", + 'collections.importFromTrip': "นำเข้าจากทริป", + 'collections.importTitle': "นำเข้าจากทริป", + 'collections.importDoneTitle': "นำเข้าเสร็จแล้ว", + 'collections.importPickTripHint': "เลือกทริปเพื่อนำสถานที่ในทริปไปยัง {name}", + 'collections.importNoTrips': "ยังไม่มีการเดินทาง", + 'collections.importPlacesCount': "{count} สถานที่", + 'collections.importSearchPlaces': "ค้นหาสถานที่...", + 'collections.importOnlyNew': "ใหม่เท่านั้น", + 'collections.importSelectAll': "เลือกทั้งหมด", + 'collections.importClearSelection': "ล้างการเลือก", + 'collections.importAlreadySaved': "บันทึกแล้ว", + 'collections.importUnscheduled': "ไม่ได้กำหนดไว้", + 'collections.importOnDay': "วันที่ {count}", + 'collections.importSelectedCount': "เลือกแล้ว {count} รายการ", + 'collections.importAction': "นำเข้า {count}", + 'collections.importEmptyTrip': "ทริปนี้ยังไม่มีสถานที่", + 'collections.importNothingNew': "ทุกอย่างจากทริปนี้อยู่ในรายการนี้แล้ว", + 'collections.importDone': "เพิ่มสถานที่ {count} แล้ว", + 'collections.importDoneSkipped': "{count} อยู่ในรายการแล้วและยังคงอยู่เหมือนเดิม", + 'collections.importDoneClean': "ตอนนี้สถานที่ทั้งหมดอยู่ใน {name} แล้ว", + 'collections.sort.default': "ค่าเริ่มต้น", + 'collections.sort.nameAsc': "ชื่อ (ก-ฮ)", + 'collections.coordinates': "พิกัด", + 'collections.showList': "แสดงรายการ", + 'collections.expandMap': "ขยายแผนที่", + 'collections.hero.mine': "คอลเลกชันของฉัน", + 'collections.hero.shared': "แบ่งปันกับคุณ", + 'collections.hero.all': "ห้องสมุดของคุณ", + 'collections.title': "คอลเลกชัน", + 'collections.subtitle': "สถานที่ที่บันทึกไว้ของคุณจัดเป็นรายการ", + + 'collections.newList': "รายการใหม่", + 'collections.create': "สร้าง", + 'collections.editList': "เปลี่ยนชื่อ", + 'collections.listMenu': "ตัวเลือกรายการ", + 'collections.deleteList': "ลบรายการ", + 'collections.deleteListConfirm': + "การดำเนินการนี้จะลบรายการและสถานที่ที่บันทึกไว้ทั้งหมดอย่างถาวร สิ่งนี้ไม่สามารถยกเลิกได้", + 'collections.listName': "ชื่อรายการ", + 'collections.listNamePlaceholder': "เช่น โตเกียว 2025", + 'collections.listColor': "สี", + 'collections.allSaved': "บันทึกทั้งหมดแล้ว", + 'collections.shared': "แบ่งปันแล้ว", + + 'collections.empty.title': "ยังไม่มีสถานที่", + 'collections.empty.text': "บันทึกสถานที่จากการเดินทางเพื่อสร้างรายการนี้", + 'collections.empty.noMatchTitle': "ไม่พบรายการที่ตรงกัน", + 'collections.empty.noMatchText': "ไม่มีสถานที่ที่บันทึกไว้ซึ่งตรงกับตัวกรองหรือการค้นหาของคุณ", + 'collections.empty.firstTitle': "เริ่มคอลเลกชันแรกของคุณ", + 'collections.empty.firstText': "สร้างรายการเพื่อบันทึกสถานที่ที่คุณต้องการจดจำตลอดการเดินทาง", + + 'collections.view.grid': "กริด", + 'collections.view.list': "รายการ", + 'collections.view.map': "แผนที่", + + 'collections.status.idea': "ไอเดีย", + 'collections.status.want': "อยากไป", + 'collections.status.visited': "เยี่ยมชมแล้ว", + 'collections.status.filterAll': "ทั้งหมด", + 'collections.status.cycleHint': "แตะเพื่อเปลี่ยน", + + 'collections.markVisited': "ทำเครื่องหมายว่าเคยไปแล้ว", + 'collections.markVisitedAll': "ไปมาแล้วทุกสถานที่", + 'collections.markVisitedSelection': "ทำเครื่องหมายว่าเคยไปแล้วในรายการของคุณ", + 'collections.markVisitedNone': "ไม่มีสถานที่เหล่านี้บันทึกไว้ในรายการ", + 'collections.markedVisited': "ทำเครื่องหมายว่าเยี่ยมชมแล้ว", + 'collections.markedVisitedTrip': "{count} สถานที่ที่ทำเครื่องหมายว่าเคยไปแล้ว", + + 'collections.copyToTrip': "คัดลอกไปที่การเดินทาง", + 'collections.copyToTripTitle': "คัดลอกไปที่การเดินทาง", + 'collections.copyN': "คัดลอก {count} ไปยังการเดินทาง", + 'collections.copyToTripSearch': "ค้นหาการเดินทาง", + 'collections.searchLists': "ค้นหารายการ", + 'collections.copyToTripConfirm': "คัดลอก", + 'collections.noTrips': "ยังไม่มีการเดินทาง", + 'collections.alreadyInTrip': "อยู่แล้วในทริปนี้", + 'collections.copied': "คัดลอกไปที่การเดินทาง", + 'collections.copiedCount': "คัดลอก {count} สถานที่แล้ว", + 'collections.skippedDuplicates': "ข้าม {count} รายการที่ซ้ำกัน", + 'collections.copyNothing': "ไม่มีอะไรจะคัดลอก", + 'collections.removeFromList': "ลบออกจากรายการ", + 'collections.removeFromListConfirm': "ลบสถานที่นี้ออกจากรายการใช่ไหม", + 'collections.removeFromCollection': "ลบออกจากคอลเลกชัน", + + 'collections.saved': "บันทึกไปที่ {name}", + 'collections.savedUndo': "เลิกทำ", + 'collections.viewInCollection': "ดู", + 'collections.duplicateWarning': "สถานที่นี้อยู่ในรายการแล้ว", + + 'collections.search': "ค้นหาสถานที่", + 'collections.selectMode': "เลือก", + 'collections.selectedCount': "เลือกแล้ว {count} รายการ", + + 'collections.pickList': "บันทึกลงในรายการ", + 'collections.pickListPlaceholder': "เลือกรายการ", + 'collections.addedToList': "เพิ่มไปที่ {name} แล้ว", + 'collections.removedFromList': "ลบออกจาก {name}", + 'collections.inLists': "ในรายการของคุณ", + 'collections.otherLists': "เพิ่มลงในรายการ", + 'collections.noListsYet': "สร้างรายการก่อนเพื่อบันทึกสถานที่", + 'collections.removedFromAll': "ลบออกจากคอลเลกชันแล้ว", + 'collections.picker.title': "สถานที่ที่บันทึกไว้", + 'collections.picker.showMore': "แสดง {count} เพิ่มเติม", + 'collections.picker.search': "ค้นหาสถานที่ที่บันทึกไว้", + 'collections.picker.empty': "ไม่มีสถานที่ที่บันทึกไว้ที่จะเพิ่ม", + 'collections.picker.hint': "เลือกสถานที่จากคอลเล็กชันของคุณ", + 'collections.picker.use': "ใช้", + + 'collections.share.title': "แชร์รายการ", + 'collections.share.titleNamed': "แบ่งปัน “{name}”", + 'collections.share.button': "แบ่งปัน", + 'collections.share.members': "สมาชิก", + 'collections.share.owner': "เจ้าของ", + 'collections.share.you': "คุณ", + 'collections.share.pending': "รอคำเชิญ", + 'collections.share.accepted': "ได้รับการยอมรับ", + 'collections.share.invite': "เชิญใครสักคน", + 'collections.share.inviteUser': "เลือกผู้ใช้", + 'collections.share.sendInvite': "ส่งคำเชิญ", + 'collections.share.inviteHint': "ผู้ที่ได้รับเชิญสามารถดูและแก้ไขรายการนี้ได้", + 'collections.share.noUsers': "ไม่มีผู้ใช้ที่สามารถเชิญได้", + 'collections.share.memberHint': "มีเพียงเจ้าของรายการเท่านั้นที่สามารถเชิญหรือลบบุคคลได้", + 'collections.share.cancel': "ยกเลิก", + 'collections.share.leave': "ออกจากรายการ", + 'collections.share.leaveConfirm': "ออกจากรายการที่แชร์นี้ใช่ไหม คุณจะสูญเสียการเข้าถึงจนกว่าคุณจะได้รับเชิญอีกครั้ง", + 'collections.share.left': "คุณออกจากรายการแล้ว", + 'collections.share.remove': "ลบ", + + 'collections.invites.title': "คำเชิญ", + 'collections.invites.from': "จาก", + 'collections.invites.accept': "ยอมรับ", + 'collections.invites.decline': "ปฏิเสธ", + 'collections.invites.received': "คุณมีคำเชิญรายการใหม่", + 'collections.invite.sent': "ส่งคำเชิญแล้ว", + 'collections.invite.error': "ไม่สามารถส่งคำเชิญได้", + 'collections.invite.accepted': "ตอบรับคำเชิญแล้ว", + 'collections.invite.declined': "คำเชิญถูกปฏิเสธ", + + 'collections.widget.title': "คอลเลกชัน", + 'collections.widget.empty': "ยังไม่มีสถานที่ที่บันทึกไว้", + 'collections.widget.savedCount': "{count} บันทึกแล้ว", + + 'collections.labels.title': "ป้ายกำกับ", + 'collections.labels.manage': "จัดการป้ายกำกับ", + 'collections.labels.add': "เพิ่มป้ายกำกับ", + 'collections.labels.name': "ชื่อป้ายกำกับ", + 'collections.labels.namePlaceholder': "เช่น เบอร์ลิน", + 'collections.labels.assign': "กำหนดป้ายกำกับ", + 'collections.labels.assignN': "เพิ่มป้ายกำกับให้กับสถานที่ {count}", + 'collections.labels.assignedCount': "ติดป้ายกำกับ {count} สถานที่", + 'collections.labels.empty': "ยังไม่มีป้ายกำกับ", + 'collections.labels.emptyHint': "สร้างป้ายกำกับก่อนเพื่อจัดกลุ่มสถานที่ในรายการนี้", + 'collections.file.export': "ส่งออก", + 'collections.file.exportTitle': "ดาวน์โหลดรายการนี้เป็นไฟล์", + 'collections.file.importButton': "นำเข้ารายการจากไฟล์", + 'collections.file.importTitle': "นำเข้ารายการ", + 'collections.file.choose': "เลือกไฟล์รายการ", + 'collections.file.confirm': "นำเข้า", + 'collections.file.change': "เปลี่ยน", + 'collections.file.labelCount': "{count} ป้ายกำกับ", + 'collections.file.hint': "สถานที่จะเข้ามาเป็นรายการใหม่ของคุณเอง คะแนน สมาชิก และรูปภาพที่อัปโหลดจะไม่ถูกนำมาด้วย", + 'collections.file.done': "นำเข้าสถานที่ {count} แห่งแล้ว", + 'collections.file.doneSkipped': "นำเข้าสถานที่ {count} แห่งแล้ว ข้าม {skipped} แห่ง", + 'collections.file.errorTooLarge': "ไฟล์นั้นใหญ่เกินกว่าจะเป็นรายการได้", + 'collections.file.errorUnreadable': "ไม่สามารถอ่านไฟล์นั้นได้", + 'collections.file.errorNotACollection': "ไฟล์นั้นไม่ใช่ไฟล์รายการของ TREK", +}; + +export default collection; diff --git a/shared/src/i18n/th/common.ts b/shared/src/i18n/th/common.ts new file mode 100644 index 000000000..31a148e69 --- /dev/null +++ b/shared/src/i18n/th/common.ts @@ -0,0 +1,77 @@ +import type { TranslationStrings } from '../types'; + +const common: TranslationStrings = { + 'common.save': "บันทึก", + 'common.showMore': "แสดงเพิ่มเติม", + 'common.showLess': "แสดงน้อยลง", + 'common.cancel': "ยกเลิก", + 'common.clear': "ล้าง", + 'common.delete': "ลบ", + 'common.preview': "ดูตัวอย่าง", + 'common.edit': "แก้ไข", + 'common.add': "เพิ่ม", + 'common.loading': "กำลังโหลด...", + 'common.import': "นำเข้า", + 'common.select': "เลือก", + 'common.selectAll': "เลือกทั้งหมด", + 'common.deselectAll': "ยกเลิกการเลือกทั้งหมด", + 'common.error': "เกิดข้อผิดพลาด", + 'common.success': "สำเร็จ", + 'common.unknownError': "ข้อผิดพลาดที่ไม่รู้จัก", + 'common.tooManyAttempts': "มีความพยายามมากเกินไป โปรดลองอีกครั้งในภายหลัง", + 'common.back': "กลับ", + 'common.all': "ทั้งหมด", + 'common.close': "ปิด", + 'common.open': "เปิด", + 'common.upload': "อัปโหลด", + 'common.search': "ค้นหา", + 'common.confirm': "ยืนยัน", + 'common.ok': "ตกลง", + 'common.yes': "ใช่", + 'common.no': "ไม่", + 'common.or': "หรือ", + 'common.none': "ไม่มี", + 'common.date': "วันที่", + 'common.rename': "เปลี่ยนชื่อ", + 'common.discardChanges': "ยกเลิกการเปลี่ยนแปลง", + 'common.discard': "ทิ้ง", + 'common.name': "ชื่อ", + 'common.email': "อีเมล", + 'common.password': "รหัสผ่าน", + 'common.saving': "กำลังบันทึก...", + 'common.justNow': "เมื่อสักครู่", + 'common.hoursAgo': "{count}ชม. ที่แล้ว", + 'common.daysAgo': "{count} วัน ที่แล้ว", + 'common.saved': "บันทึกแล้ว", + 'common.update': "อัปเดต", + 'common.change': "เปลี่ยน", + 'common.uploading': "กำลังอัปโหลด...", + 'common.backToPlanning': "กลับไปที่การวางแผน", + 'common.reset': "รีเซ็ต", + 'common.expand': "ขยาย", + 'common.collapse': "ยุบ", + 'common.copy': "คัดลอก", + 'common.copied': "คัดลอกแล้ว", + 'common.datepicker.prevMonth': "เดือนที่แล้ว", + 'common.datepicker.nextMonth': "เดือนหน้า", + 'common.datepicker.prevYear': "ปีที่แล้ว", + 'common.datepicker.nextYear': "ปีหน้า", + 'common.datepicker.prevYears': "ปีก่อนๆ", + 'common.datepicker.nextYears': "ปีหน้า", + 'common.datepicker.selectMonth': "เลือกเดือน", + 'common.datepicker.selectYear': "เลือกปี", + 'common.datepicker.enterManually': "ป้อนวันที่ด้วยตนเอง", + 'common.datepicker.typeDate': "พิมพ์วันที่", + 'common.datepicker.dialog': "ตัวเลือกวันที่", + 'common.datepicker.clearDate': "ล้างวันที่", + 'common.errorTitle': "มีบางอย่างผิดพลาด", + 'common.errorBody': "แอปส่วนนี้หยุดทำงาน ข้อมูลของคุณปลอดภัย", + 'common.errorPanelTitle': "ไม่สามารถแสดงส่วนนี้ได้", + 'common.errorPanelBody': "หน้าที่เหลือยังคงใช้งานได้", + 'common.errorRetry': "ลองอีกครั้ง", + 'common.errorReload': "โหลดหน้าซ้ำ", + 'common.errorUpdateTitle': "มีเวอร์ชันใหม่ให้ใช้งานแล้ว", + 'common.errorUpdateBody': "TREK ได้รับการอัปเดตขณะที่แท็บนี้เปิดอยู่ โหลดซ้ำเพื่อรับเวอร์ชันใหม่", + 'common.errorPluginTitle': "ไม่สามารถแสดงปลั๊กอินนี้ได้", +}; +export default common; diff --git a/shared/src/i18n/th/dashboard.ts b/shared/src/i18n/th/dashboard.ts new file mode 100644 index 000000000..a7617f872 --- /dev/null +++ b/shared/src/i18n/th/dashboard.ts @@ -0,0 +1,189 @@ +import type { TranslationStrings } from '../types'; + +const dashboard: TranslationStrings = { + '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.newTripSub': "วางแผนการเดินทางใหม่ตั้งแต่ต้น", + 'dashboard.subscribeAllTrips': "สมัครสมาชิกทุกทริป", + 'dashboard.subscribeAllTripsDesc': + "ฟีดปฏิทินเดียวสำหรับการเดินทางที่ใช้งานอยู่ทั้งหมดของคุณ โดยจะซิงค์โดยอัตโนมัติ ไม่รวมการเดินทางที่เก็บถาวรและการเดินทางที่สิ้นสุดเกิน 90 วันที่ผ่านมา", + 'dashboard.gridView': "มุมมองตาราง", + 'dashboard.listView': "มุมมองรายการ", + 'dashboard.currency': "สกุลเงิน", + 'dashboard.timezone': "เขตเวลา", + 'dashboard.localTime': "ท้องถิ่น", + 'dashboard.timezoneCustomTitle': "เขตเวลาที่กำหนดเอง", + 'dashboard.timezoneCustomLabelPlaceholder': "ป้ายกำกับ (ไม่บังคับ)", + 'dashboard.timezoneCustomTzPlaceholder': "เช่น America/New_York", + 'dashboard.timezoneCustomAdd': "เพิ่ม", + 'dashboard.timezoneCustomErrorEmpty': "ป้อนตัวระบุเขตเวลา", + '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.loadErrorBanner': "ไม่สามารถเข้าถึงเซิร์ฟเวอร์ได้ การเดินทางของคุณปลอดภัย — โปรดลองอีกครั้ง", + 'dashboard.retry': "ลองอีกครั้ง", + '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.confirm.copy.title': "คัดลอกการเดินทางนี้ใช่ไหม", + 'dashboard.confirm.copy.willCopy': "จะถูกคัดลอก", + 'dashboard.confirm.copy.will1': "วัน สถานที่ และการกำหนดวัน", + 'dashboard.confirm.copy.will2': "ที่พักและการจอง", + 'dashboard.confirm.copy.will3': "รายการงบประมาณและลำดับหมวดหมู่", + 'dashboard.confirm.copy.will4': "รายการจัดกระเป๋า (ยังไม่ติ๊ก)", + 'dashboard.confirm.copy.will5': "สิ่งที่ต้องทำ (ไม่ได้มอบหมายและไม่ได้เลือก)", + 'dashboard.confirm.copy.will6': "บันทึกประจำวัน", + 'dashboard.confirm.copy.wontCopy': "จะไม่ถูกคัดลอก", + 'dashboard.confirm.copy.wont1': "ผู้ทำงานร่วมกันและการมอบหมายสมาชิก", + 'dashboard.confirm.copy.wont2': "บันทึกการทำงานร่วมกัน แบบสำรวจ และข้อความ", + 'dashboard.confirm.copy.wont3': "ไฟล์และรูปถ่าย", + 'dashboard.confirm.copy.wont4': "โทเค็นสำหรับแชร์", + 'dashboard.confirm.copy.confirm': "คัดลอกการเดินทาง", + '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.coverSaveError': "ไม่สามารถบันทึกภาพหน้าปกได้", + 'dashboard.coverRemoveError': "ลบไม่สำเร็จ", + 'dashboard.searchUnsplash': "ค้นหา Unsplash", + 'dashboard.unsplashSearchPlaceholder': "ค้นหาภาพถ่ายปลายทาง", + 'dashboard.unsplashQueryRequired': "ป้อนคำค้นหา", + 'dashboard.unsplashNoResults': "ไม่พบภาพ", + 'dashboard.coverSearchError': "ไม่สามารถค้นหา Unsplash", + 'dashboard.useUnsplashPhoto': "ใช้รูปภาพ Unsplash โดย {photographer}", + 'dashboard.titleRequired': "ต้องระบุชื่อ", + 'dashboard.endDateError': "วันที่สิ้นสุดต้องอยู่หลังวันที่เริ่มต้น", + 'dashboard.dateShiftTitle': "วันที่เริ่มต้นใหม่", + 'dashboard.dateShiftIntro': "คุณเปลี่ยนวันที่เริ่มต้นของการเดินทางครั้งนี้ แผนของคุณควรปรับตามวันที่ใหม่อย่างไร", + 'dashboard.dateShiftKeepBookings': "ทำการจองตามวันที่ของพวกเขา", + 'dashboard.dateShiftKeepBookingsDesc': + "แผนรายวันจะเปลี่ยนไปตามวันที่ใหม่ ในขณะที่การจองและที่พักจะยังคงเป็นวันที่เดิม ตราบใดที่ยังเป็นส่วนหนึ่งของการเดินทาง", + 'dashboard.dateShiftAll': "เลื่อนทุกอย่างตามวันใหม่", + 'dashboard.dateShiftAllDesc': + "แผนการเดินทางทั้งหมดจะย้ายไปพร้อมกับวันที่ใหม่ รวมถึงการจองและที่พัก", + 'dashboard.dateShiftHint': "เคล็ดลับ: หากต้องการเปลี่ยนแผนการเดินทางเพียงบางส่วน ให้ใช้ \"เพิ่มวัน\" ในเครื่องมือวางแผนแทน", + '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.addCoverImage': "เพิ่มภาพหน้าปก", + '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.spotlightDayOf': "วันที่ {day} จาก {total}", + 'dashboard.mobile.spotlightDayOne': "{count} วัน", + 'dashboard.mobile.spotlightDaysMany': "{count} วัน", + 'dashboard.mobile.completed': "เสร็จสิ้น", + 'dashboard.mobile.currencyConverter': "แปลงสกุลเงิน", + 'dashboard.filter.planned': "วางแผนแล้ว", + 'dashboard.hero.badgeLive': "ถ่ายทอดสดตอนนี้", + 'dashboard.hero.badgeToday': "เริ่มวันนี้", + 'dashboard.hero.badgeTomorrow': "พรุ่งนี้", + 'dashboard.hero.badgeNext': "ถัดไป", + 'dashboard.hero.badgeRecent': "ล่าสุด", + 'dashboard.hero.tripDates': "วันเดินทาง", + 'dashboard.hero.noDates': "ยังไม่กำหนดวัน", + 'dashboard.hero.travelerOne': "{count} นักเดินทาง", + 'dashboard.hero.travelerMany': "นักเดินทาง {count}", + 'dashboard.hero.destinationOne': "{count} ปลายทาง", + 'dashboard.hero.destinationMany': "{count} จุดหมายปลายทาง", + 'dashboard.hero.dayUnitOne': "วัน", + 'dashboard.hero.dayUnitMany': "วัน", + 'dashboard.hero.dayLeft': "วันคงเหลือ", + 'dashboard.hero.daysLeft': "วันคงเหลือ", + 'dashboard.hero.lastDay': "วันสุดท้าย", + 'dashboard.hero.untilStart': "จนกระทั่งเริ่มต้น", + 'dashboard.hero.startsIn': "การเดินทางเริ่มต้นใน", + 'dashboard.atlas.countriesVisited': "แผนที่ · ประเทศที่เยี่ยมชม", + 'dashboard.atlas.ofTotal': "ของ {total}", + 'dashboard.atlas.tripsTotal': "ทริปทั้งหมด", + 'dashboard.atlas.placesMapped': "{count} สถานที่ที่แมปแล้ว", + 'dashboard.atlas.daysTraveled': "วันเดินทาง", + 'dashboard.atlas.daysUnit': "วัน", + 'dashboard.atlas.acrossAllTrips': "ตลอดทุกการเดินทาง", + 'dashboard.atlas.distanceFlown': "ระยะทางที่บิน", + 'dashboard.atlas.kmUnit': "กม", + 'dashboard.atlas.aroundEquator': "ประมาณ {count}× รอบเส้นศูนย์สูตร", + 'dashboard.card.idea': "ไอเดีย", + 'dashboard.card.buddyOne': "บัดดี้", + 'dashboard.fx.from': "จาก", + 'dashboard.fx.to': "ถึง", + 'dashboard.fx.unavailable': "อัตราไม่พร้อมใช้งาน", + 'dashboard.tz.searchPlaceholder': "ค้นหาเขตเวลา...", + 'dashboard.tz.empty': "ยังไม่มีเขตเวลาอื่น — เพิ่มหนึ่งด้วย +", + 'dashboard.upcoming.title': "การจองที่จะเกิดขึ้น", + 'dashboard.upcoming.empty': "ยังไม่มีการจองอะไรเลย", + 'dashboard.aria.toggleView': "สลับมุมมอง", + 'dashboard.aria.filter': "ตัวกรอง", + 'dashboard.aria.duplicate': "ทำซ้ำ", + 'dashboard.aria.refreshRates': "รีเฟรชอัตราแลกเปลี่ยน", + 'dashboard.aria.swapCurrencies': "สลับสกุลเงิน", + 'dashboard.aria.addTimezone': "เพิ่มเขตเวลา", + 'dashboard.aria.removeTimezone': "ลบ {city}", + 'dashboard.dayCountRequired': "ต้องระบุจำนวนวัน", +}; +export default dashboard; diff --git a/shared/src/i18n/th/dawarich.ts b/shared/src/i18n/th/dawarich.ts new file mode 100644 index 000000000..7f66cd2ca --- /dev/null +++ b/shared/src/i18n/th/dawarich.ts @@ -0,0 +1,153 @@ +import type { TranslationStrings } from '../types'; + +const dawarich: TranslationStrings = { + 'dawarich.title': "Dawarich", + 'dawarich.intro': "เชื่อมต่ออินสแตนซ์ Dawarich ของคุณเพื่อดูว่าคุณไปที่ใดมาจริง ๆ TREK จะอ่านข้อมูลและแนะนำรายการบันทึก สถานที่ และประเทศ โดยจะไม่เพิ่มข้อมูลจนกว่าคุณจะยืนยัน และจะไม่เขียนข้อมูลกลับไปยัง Dawarich", + 'dawarich.url': "ที่อยู่ของอินสแตนซ์", + 'dawarich.apiKey': "คีย์ API", + 'dawarich.apiKeyPlaceholder': "วางคีย์ API ของ Dawarich", + 'dawarich.apiKeyHint': "พบได้ใน Dawarich ที่ บัญชี → คีย์ API จัดเก็บแบบเข้ารหัสและจะไม่แสดงอีก", + 'dawarich.allowInsecureTls': "อนุญาตใบรับรองแบบลงนามเอง", + 'dawarich.allowInsecureTlsHint': "จำเป็นเฉพาะเมื่ออินสแตนซ์ของคุณใช้ใบรับรองที่เซิร์ฟเวอร์ไม่เชื่อถือ", + 'dawarich.syncEnabled': "ตรวจหาการพักใหม่โดยอัตโนมัติ", + 'dawarich.syncEnabledHint': "เมื่อปิด TREK จะอ่าน Dawarich เฉพาะเมื่อคุณสั่ง", + 'dawarich.test.button': "ทดสอบการเชื่อมต่อ", + 'dawarich.test.success': "เชื่อมต่อแล้ว พบการพัก {count} รายการใน 30 วันที่ผ่านมา", + 'dawarich.test.failed': "ไม่สามารถเชื่อมต่อ Dawarich ได้", + 'dawarich.syncNow': "ตรวจสอบตอนนี้", + 'dawarich.connected': "เชื่อมต่อแล้ว", + 'dawarich.notConnected': "ยังไม่ได้เชื่อมต่อ", + 'dawarich.disconnect': "ตัดการเชื่อมต่อ", + 'dawarich.lastSync': "ตรวจสอบล่าสุด {when}", + 'dawarich.neverSynced': "ยังไม่เคยตรวจสอบ", + 'dawarich.syncPartial': "อ่านบางทริปไม่ได้", + 'dawarich.serverVersion': "Dawarich {version}", + 'dawarich.toast.saved': "บันทึกการเชื่อมต่อ Dawarich แล้ว", + 'dawarich.toast.saveError': "บันทึกการเชื่อมต่อไม่ได้", + 'dawarich.toast.disconnected': "ตัดการเชื่อมต่อ Dawarich แล้ว", + 'dawarich.toast.synced': "พบการพักใหม่ {count} รายการ", + 'dawarich.toast.syncError': "อ่าน Dawarich ไม่ได้", + 'dawarich.toast.syncRunning': "มีการตรวจสอบกำลังทำงานอยู่", + 'dawarich.toast.acceptError': "เพิ่มรายการนี้ไม่ได้", + 'dawarich.toast.updateError': "อัปเดตคำแนะนำนี้ไม่ได้", + 'dawarich.toast.accepted.place': "เพิ่มลงในทริปแล้ว", + 'dawarich.toast.accepted.journal': "เพิ่มลงในบันทึกแล้ว", + 'dawarich.toast.accepted.bucket_list': "ทำเครื่องหมายว่าไปถึงในรายการอยากไปแล้ว", + 'dawarich.capability.visits': "การพัก", + 'dawarich.capability.track': "เส้นทางที่บันทึกไว้", + 'dawarich.capability.locations': "การจับคู่รายการอยากไป", + 'dawarich.capability.visitedCities': "ประเทศและเมือง", + 'dawarich.capability.missing': "Dawarich เวอร์ชันนี้ไม่มี: {features}", + 'dawarich.error.unreachable': "TREK เชื่อมต่อไปยังที่อยู่นั้นไม่ได้", + 'dawarich.error.unauthorized': "Dawarich ปฏิเสธคีย์ API", + 'dawarich.error.forbidden': "คีย์ API นี้ไม่มีสิทธิ์อ่านข้อมูลนี้", + 'dawarich.error.not_found': "Dawarich เวอร์ชันนี้ไม่มีปลายทางนั้น", + 'dawarich.error.rate_limited': "Dawarich ขอให้ TREK ช้าลง ลองใหม่อีกสักครู่", + 'dawarich.error.server_error': "Dawarich ตอบกลับพร้อมข้อผิดพลาด", + 'dawarich.error.invalid_response': "ที่อยู่นั้นตอบกลับด้วยข้อมูลที่ไม่ใช่ Dawarich", + 'dawarich.error.too_large': "Dawarich ส่งข้อมูลมากเกินกว่าที่ TREK จะอ่านได้ในครั้งเดียว", + 'dawarich.error.not_connected': "ยังไม่ได้เชื่อมต่ออินสแตนซ์ Dawarich", + 'dawarich.error.addon_disabled': "ส่วนเสริม Dawarich ถูกปิดสำหรับอินสแตนซ์นี้", + 'dawarich.error.offline': "ต้องใช้การเชื่อมต่อ — ขณะนี้ TREK ออฟไลน์", + 'dawarich.error.invalid_url': "TREK ใช้ที่อยู่นั้นไม่ได้", + 'dawarich.warning.private_ip': "ที่อยู่นั้นชี้ไปยัง IP ส่วนตัว ({ip}) โปรดตรวจสอบว่าเป็นสิ่งที่คุณต้องการ เซิร์ฟเวอร์อาจต้องตั้งค่า ALLOW_INTERNAL_NETWORK=true เพื่อเข้าถึง", + 'dawarich.error.unknown': "เกิดข้อผิดพลาดขณะสื่อสารกับ Dawarich", + 'dawarich.trail.show': "แสดงเส้นทางที่บันทึกไว้", + 'dawarich.trail.hide': "ซ่อนเส้นทางที่บันทึกไว้", + 'dawarich.trail.loading': "กำลังโหลดเส้นทางที่บันทึกไว้…", + 'dawarich.trail.empty': "ไม่มีสิ่งใดถูกบันทึกในช่วงวันที่นี้", + 'dawarich.trail.offline': "เส้นทางที่บันทึกไว้ต้องใช้การเชื่อมต่อ", + 'dawarich.trail.unavailable': "โหลดเส้นทางที่บันทึกไว้ไม่ได้", + 'dawarich.duration.minutes': "{minutes} นาที", + 'dawarich.duration.hours': "{hours} ชม.", + 'dawarich.duration.hoursMinutes': "{hours} ชม. {minutes} นาที", + 'dawarich.checkedAgo': "ตรวจสอบ {ago} ที่แล้ว", + 'dawarich.badge.lowConfidence': "ไม่แน่ใจ", + 'dawarich.badge.sourceChanged': "มีการเปลี่ยนแปลงใน Dawarich", + 'dawarich.badge.sourceMissing': "ไม่มีใน Dawarich แล้ว", + 'dawarich.suggestions.title': "จาก Dawarich", + 'dawarich.suggestions.pending': "รอคุณอยู่ {count} รายการ", + 'dawarich.suggestions.loading': "กำลังอ่าน Dawarich…", + 'dawarich.suggestions.notConnected': "เชื่อมต่อ Dawarich ในการตั้งค่าเพื่อดูการพักของคุณที่นี่", + 'dawarich.suggestions.unavailable': "อ่าน Dawarich ไม่ได้", + 'dawarich.suggestions.allHandled': "จัดการข้อมูลที่บันทึกไว้ที่นี่ครบแล้ว", + 'dawarich.suggestions.asJournal': "เขียนรายการบันทึก", + 'dawarich.suggestions.asPlace': "เพิ่มเป็นสถานที่", + 'dawarich.suggestions.dismiss': "ไม่ใช่สถานที่ที่ฉันไป", + 'dawarich.suggestions.dismissed': "ปิดคำแนะนำแล้ว", + 'dawarich.suggestions.restore': "นำกลับ", + 'dawarich.suggestions.showHandled': "แสดง {count} รายการที่จัดการแล้ว", + 'dawarich.suggestions.hideHandled': "ซ่อนรายการที่จัดการแล้ว", + 'dawarich.suggestions.matchesWish': "อยู่ในรายการอยากไปของคุณ: {name}", + 'dawarich.suggestions.acceptedAs.place': "เพิ่มเป็นสถานที่แล้ว", + 'dawarich.suggestions.acceptedAs.journal': "อยู่ในบันทึกแล้ว", + 'dawarich.suggestions.acceptedAs.bucket_list': "ทำเครื่องหมายความปรารถนาแล้ว", + 'dawarich.suggestions.sourceChanged': "การพักนี้เปลี่ยนแปลงใน Dawarich หลังจากที่คุณนำไปใช้ สิ่งที่คุณเขียนใน TREK จะไม่เปลี่ยน", + 'dawarich.suggestions.sourceMissing': "การพักนี้ไม่มีอยู่ใน Dawarich แล้ว สิ่งที่คุณเขียนใน TREK จะไม่เปลี่ยน", + 'dawarich.sourceStatus.suggested': "ตรวจพบแล้ว แต่ยังไม่ยืนยัน", + 'dawarich.confidence.high': "ตรวจพบอย่างมั่นใจ", + 'dawarich.confidence.medium': "ตรวจพบค่อนข้างมั่นใจ", + 'dawarich.confidence.low': "ตรวจพบอย่างไม่แน่ใจ", + 'dawarich.accept.title.place': "เพิ่มการพักนี้เป็นสถานที่", + 'dawarich.accept.title.journal': "เขียนรายการบันทึก", + 'dawarich.accept.title.bucket_list': "ทำเครื่องหมายความปรารถนาว่าสำเร็จ", + 'dawarich.accept.confirm.place': "เพิ่มสถานที่", + 'dawarich.accept.confirm.journal': "เพิ่มรายการ", + 'dawarich.accept.confirm.bucket_list': "ทำเครื่องหมายว่าสำเร็จ", + 'dawarich.accept.recorded': "บันทึกตั้งแต่ {from} ถึง {to}", + 'dawarich.accept.duration': "{minutes} นาที", + 'dawarich.accept.name': "ชื่อ", + 'dawarich.accept.date': "วันที่", + 'dawarich.accept.from': "มาถึง", + 'dawarich.accept.to': "ออก", + 'dawarich.accept.trip': "ทริป", + 'dawarich.accept.thisTrip': "ทริปนี้", + 'dawarich.accept.pickTrip': "เลือกทริป", + 'dawarich.accept.day': "วัน", + 'dawarich.accept.noDay': "ยังไม่ได้อยู่ในวัน", + 'dawarich.accept.journal': "บันทึก", + 'dawarich.accept.pickJournal': "เลือกบันทึก", + 'dawarich.accept.notes': "หมายเหตุ", + 'dawarich.accept.story': "เรื่องราวของคุณ", + 'dawarich.accept.storyPlaceholder': "เกิดอะไรขึ้นที่นี่?", + 'dawarich.accept.photosHint': "เพิ่มรูปภาพในรายการได้หลังจากสร้างแล้ว", + 'dawarich.place.fromDawarich': "เพิ่มจากบันทึก Dawarich ของคุณ", + 'dawarich.bucket.title': "ตรวจสอบรายการอยากไปของคุณกับ Dawarich", + 'dawarich.bucket.description': "ค้นหาสถานที่ที่คุณอยากไปจากบันทึกของคุณ การเยี่ยมชมต้องอยู่ใกล้และใช้เวลา ณ จุดนั้น การขับผ่านไม่นับ", + 'dawarich.bucket.scan': "ตรวจสอบรายการอยากไป", + 'dawarich.bucket.scanning': "กำลังตรวจสอบ…", + 'dawarich.bucket.noMatches': "ไม่พบสถานที่จากรายการอยากไปในบันทึกของคุณ", + 'dawarich.bucket.alreadyVisited': "ทำเครื่องหมายว่าสำเร็จแล้ว", + 'dawarich.bucket.confirm': "ทำเครื่องหมายว่าสำเร็จ {count} รายการ", + 'dawarich.bucket.confirmed': "ทำเครื่องหมายความปรารถนาสำเร็จ {count} รายการ", + 'dawarich.bucket.skipped': "มี {count} รายการที่ไม่มีพิกัด จึงตรวจสอบไม่ได้", + 'dawarich.bucket.truncated': "ตรวจสอบเฉพาะรายการแรก ๆ แล้ว เรียกใช้อีกครั้งสำหรับส่วนที่เหลือ", + 'dawarich.bucket.visitedFrom': "ทำเครื่องหมายว่าสำเร็จจากบันทึก Dawarich ของคุณ", + 'dawarich.bucket.clearVisit': "เลิกทำ", + 'dawarich.atlas.title': "ประเทศจาก Dawarich", + 'dawarich.atlas.description': "ประเทศที่บันทึกของคุณระบุว่าคุณเคยอยู่ ยืนยันประเทศที่คุณต้องการใน Atlas — จะไม่มีการเพิ่มเอง และสิ่งที่คุณทำเครื่องหมายเองยังเป็นของคุณ", + 'dawarich.atlas.load': "ค้นหาประเทศ", + 'dawarich.atlas.loading': "กำลังอ่านบันทึกของคุณ…", + 'dawarich.atlas.empty': "บันทึกของคุณไม่แสดงประเทศใหม่ที่ TREK ยังไม่มี", + 'dawarich.atlas.cities': "{count} เมือง", + 'dawarich.atlas.citiesOne': "1 เมือง", + 'dawarich.atlas.accept': "เพิ่ม {count} ประเทศ", + 'dawarich.atlas.accepted': "เพิ่ม {count} ประเทศแล้ว", + 'dawarich.atlas.unresolved': "TREK จับคู่รายการเหล่านี้กับประเทศไม่ได้: {names}", + 'dawarich.atlas.source': "จาก Dawarich", + 'dawarich.atlas.range': "ตรวจสอบ {from} ถึง {to}", + 'dawarich.atlas.trigger': "ความปรารถนาและประเทศจากบันทึกของคุณ", + 'dawarich.atlas.dialogSubtitle': "สิ่งที่บันทึกของคุณบอกเกี่ยวกับ Atlas", + 'dawarich.atlas.tab.wishes': "รายการอยากไป", + 'dawarich.atlas.tab.countries': "ประเทศ", + 'dawarich.atlas.window': "ตรวจสอบ 12 เดือนที่ผ่านมา", + 'dawarich.selected': "เลือกแล้ว {count}", + 'dawarich.again': "ตรวจสอบอีกครั้ง", + 'dawarich.bucket.metersAway': "ห่าง {meters} ม.", + 'dawarich.bucket.kilometersAway': "ห่าง {km} กม.", + 'dawarich.bucket.rule': "จะนับว่าไปถึงเมื่ออยู่ในระยะ {meters} ม. และอยู่ที่จุดนั้นอย่างน้อย {minutes} นาที", + 'dawarich.journey.dayStays.one': "การพักจาก Dawarich 1 รายการ", + 'dawarich.journey.dayStays.other': "การพักจาก Dawarich {count} รายการ", +}; + +export default dawarich; diff --git a/shared/src/i18n/th/day.ts b/shared/src/i18n/th/day.ts new file mode 100644 index 000000000..788692fef --- /dev/null +++ b/shared/src/i18n/th/day.ts @@ -0,0 +1,26 @@ +import type { TranslationStrings } from '../types'; + +const day: TranslationStrings = { + 'day.precipProb': "ความน่าจะเป็นของฝน", + 'day.precipitation': "ปริมาณน้ำฝน", + 'day.wind': "ลม", + 'day.sunrise': "พระอาทิตย์ขึ้น", + 'day.sunset': "พระอาทิตย์ตก", + 'day.hourlyForecast': "พยากรณ์รายชั่วโมง", + 'day.climateHint': "ค่าเฉลี่ยในอดีต — การคาดการณ์จริงพร้อมใช้งานภายใน 16 วันนับจากวันที่นี้", + 'day.noWeather': "ไม่มีข้อมูลสภาพอากาศ เพิ่มสถานที่ที่มีพิกัด", + 'day.weatherFor': "พยากรณ์อากาศสำหรับ {name}", + 'day.overview': "ภาพรวมรายวัน", + 'day.accommodation': "ที่พัก", + 'day.addAccommodation': "เพิ่มที่พัก", + 'day.hotelDayRange': "นำไปใช้กับวัน", + 'day.noPlacesForHotel': "เพิ่มสถานที่ในการเดินทางของคุณก่อน", + 'day.allDays': "ทั้งหมด", + 'day.checkIn': "เช็คอิน", + 'day.checkInUntil': "เช็กอินได้ถึง", + 'day.checkOut': "เช็คเอาท์", + 'day.confirmation': "การยืนยัน", + 'day.editAccommodation': "แก้ไขที่พัก", + 'day.reservations': "การจอง", +}; +export default day; diff --git a/shared/src/i18n/th/dayplan.ts b/shared/src/i18n/th/dayplan.ts new file mode 100644 index 000000000..0be248ee6 --- /dev/null +++ b/shared/src/i18n/th/dayplan.ts @@ -0,0 +1,93 @@ +import type { TranslationStrings } from '../types'; + +const dayplan: TranslationStrings = { + 'dayplan.icsTooltip': "ส่งออกปฏิทิน (ICS)", + 'dayplan.emptyDay': "ไม่มีการวางแผนสถานที่สำหรับวันนี้", + 'dayplan.cannotReorderTransport': "การจองที่มีกำหนดเวลาไม่สามารถจัดลำดับใหม่ได้", + 'dayplan.confirmRemoveTimeTitle': "ลบเวลาเหรอ?", + 'dayplan.confirmRemoveTimeBody': + "สถานที่นี้มีเวลาที่แน่นอน ({time}) การย้ายจะลบเวลาและทำให้สามารถเรียงลำดับได้อย่างอิสระ", + 'dayplan.confirmRemoveTimeAction': "ลบเวลาและย้าย", + 'dayplan.confirmDeleteNoteTitle': "ลบบันทึกใช่ไหม", + 'dayplan.confirmDeleteNoteBody': "บันทึกนี้จะถูกลบอย่างถาวร", + 'dayplan.cannotDropOnTimed': "ไม่สามารถวางรายการระหว่างรายการที่มีขอบเขตเวลาได้", + 'dayplan.cannotBreakChronology': "การดำเนินการนี้จะทำลายลำดับเวลาของรายการตามกำหนดเวลาและการจอง", + 'dayplan.addNote': "เพิ่มหมายเหตุ", + 'dayplan.expandAll': "ขยายทั้งหมด", + 'dayplan.collapseAll': "ยุบทั้งหมด", + 'dayplan.editNote': "แก้ไขหมายเหตุ", + 'dayplan.noteAdd': "เพิ่มหมายเหตุ", + 'dayplan.noteEdit': "แก้ไขหมายเหตุ", + 'dayplan.noteDelete': "ลบบันทึก", + 'dayplan.noteTitle': "หมายเหตุ", + 'dayplan.noteSubtitle': "หมายเหตุรายวัน", + 'dayplan.noteIcon': "ไอคอน", + 'notes.appearance': "ลักษณะที่ปรากฏ", + 'notes.preview': "ดูตัวอย่าง", + 'notes.bodyPlaceholder': "รายละเอียด ลิงก์ การแจ้งเตือน...", + 'notes.markdownHint': "รองรับมาร์กดาวน์", + 'notes.format.toolbar': "การจัดรูปแบบ", + 'notes.format.bold': "ตัวหนา", + 'notes.format.italic': "ตัวเอียง", + 'notes.format.strike': "ขีดทับ", + 'notes.format.code': "รหัส", + 'notes.format.link': "ลิงก์", + 'notes.format.list': "รายการหัวข้อย่อย", + 'notes.format.orderedList': "รายการลำดับเลข", + 'notes.format.quote': "อ้าง", + 'notes.color.label': "สี", + 'notes.color.none': "ไม่มีสี", + 'notes.color.red': "สีแดง", + 'notes.color.orange': "ส้ม", + 'notes.color.amber': "อำพัน", + 'notes.color.green': "สีเขียว", + 'notes.color.cyan': "สีฟ้า", + 'notes.color.blue': "สีฟ้า", + 'notes.color.purple': "สีม่วง", + 'dayplan.totalCost': "ต้นทุนรวม", + 'dayplan.days': "วัน", + 'dayplan.dayN': "วันที่ {n}", + 'dayplan.calculating': "กำลังคำนวณ...", + 'dayplan.route': "เส้นทาง", + 'dayplan.optimize': "ปรับให้เหมาะสม", + 'dayplan.transportMode.change': "เปลี่ยนโหมดการเดินทาง", + 'dayplan.transportMode.useDefault': "ใช้ค่าเริ่มต้นของวัน", + 'dayplan.optimized': "ปรับเส้นทางให้เหมาะสม", + 'dayplan.routeError': "ไม่สามารถคำนวณเส้นทางได้", + 'dayplan.toast.needTwoPlaces': "ต้องมีอย่างน้อยสองแห่งสำหรับการเพิ่มประสิทธิภาพเส้นทาง", + 'dayplan.toast.routeOptimized': "ปรับเส้นทางให้เหมาะสม", + 'dayplan.toast.routeOptimizedFromHotel': "ปรับเส้นทางให้เหมาะสมจากที่พักของคุณ", + 'dayplan.toast.noGeoPlaces': "ไม่พบสถานที่ที่มีพิกัดในการคำนวณเส้นทาง", + 'dayplan.confirmed': "ยืนยันแล้ว", + 'dayplan.pendingRes': "รอดำเนินการ", + 'dayplan.export': "ส่งออก", + 'dayplan.exportIntro': "นำแผนการเดินทางของคุณไปใช้ในรูปแบบเอกสาร ปฏิทิน หรือ GPS", + 'dayplan.exportDocument': "เอกสาร", + 'dayplan.exportCalendar': "ปฏิทิน", + 'dayplan.exportMaps': "แผนที่และจีพีเอส", + 'dayplan.pdf': "PDF", + 'dayplan.pdfTooltip': "ส่งออกแผนวันเป็น PDF", + 'dayplan.gpxTooltip': "ส่งออกเป็น GPX สำหรับแผนที่ออฟไลน์และอุปกรณ์ GPS", + 'dayplan.gpxAll': "ทั้งทริป", + 'dayplan.gpxPlaces': "สถานที่เท่านั้น", + 'dayplan.gpxDays': "วันเป็นเส้นทาง", + 'dayplan.gpxEmpty': "ยังไม่มีสิ่งใดที่จะส่งออก", + 'dayplan.gpxFailed': "การส่งออก GPX ล้มเหลว", + 'dayplan.pdfError': "ส่งออก PDF ไม่สำเร็จ", + 'dayplan.mobile.addPlace': "เพิ่มสถานที่", + 'dayplan.mobile.searchPlaces': "ค้นหาสถานที่...", + 'dayplan.mobile.allAssigned': "ทุกสถานที่ที่ได้รับมอบหมาย", + 'dayplan.mobile.noMatch': "ไม่พบรายการที่ตรงกัน", + 'dayplan.mobile.createNew': "สร้างสถานที่ใหม่", + 'dayplan.reorderDays': "จัดลำดับวันใหม่", + 'dayplan.reorderTitle': "จัดลำดับวันใหม่", + 'dayplan.reorderHint': "สถานที่ บันทึก และการจองในแต่ละวันจะเคลื่อนไหวไปด้วย", + 'dayplan.addDay': "เพิ่มวัน", + 'dayplan.moveUp': "เลื่อนขึ้น", + 'dayplan.moveDown': "เลื่อนลง", + 'dayplan.reorderUndo': "จัดลำดับวันใหม่", + 'dayplan.reorderError': "ไม่สามารถเรียงลำดับวันใหม่ได้", + 'dayplan.addDayError': "ไม่สามารถเพิ่มวันได้", + 'dayplan.addPlaceHere': "เพิ่มสถานที่ในวันนี้", +}; +export default dayplan; diff --git a/shared/src/i18n/th/externalNotifications.ts b/shared/src/i18n/th/externalNotifications.ts new file mode 100644 index 000000000..f54d724e2 --- /dev/null +++ b/shared/src/i18n/th/externalNotifications.ts @@ -0,0 +1,77 @@ +import type { NotificationLocale } from '../externalNotifications/types'; + +const th: NotificationLocale = { + email: { + footer: 'คุณได้รับข้อความนี้เนื่องจากเปิดใช้การแจ้งเตือนใน TREK', + manage: 'จัดการการตั้งค่าในหน้าการตั้งค่า', + madeWith: 'สร้างด้วย', + openTrek: 'เปิด TREK', + }, + events: { + trip_invite: (p) => ({ + title: `คำเชิญเข้าร่วมทริป: "${p.trip}"`, + body: `${p.actor} เชิญ ${p.invitee || 'สมาชิก'} ให้เข้าร่วมทริป "${p.trip}"`, + }), + booking_change: (p) => ({ + title: `การจองใหม่: ${p.booking}`, + body: `${p.actor} เพิ่ม${p.type}ใหม่ "${p.booking}" ลงใน "${p.trip}"`, + }), + trip_reminder: (p) => ({ + title: `แจ้งเตือนทริป: ${p.trip}`, + body: `ทริป "${p.trip}" ของคุณกำลังจะมาถึงเร็ว ๆ นี้!`, + }), + todo_due: (p) => ({ + title: `งานที่ถึงกำหนด: ${p.todo}`, + body: `"${p.todo}" ใน "${p.trip}" ครบกำหนดวันที่ ${p.due}`, + }), + vacay_invite: (p) => ({ + title: 'คำเชิญรวมปฏิทินวันลา', + body: `${p.actor} เชิญคุณให้รวมแผนวันลา เปิด TREK เพื่อยอมรับหรือปฏิเสธ`, + }), + vacay_share: (p) => ({ + title: 'แชร์ปฏิทินวันลาแล้ว', + body: `${p.actor} แชร์ปฏิทินวันลาของตนกับคุณ เปิด TREK เพื่อดู`, + }), + collection_invite: (p) => ({ + title: 'คำเชิญให้แชร์คอลเลกชัน', + body: `${p.actor} เชิญคุณให้แชร์คอลเลกชัน เปิด TREK เพื่อยอมรับหรือปฏิเสธ`, + }), + photos_shared: (p) => ({ + title: `แชร์รูปภาพ ${p.count} รูปแล้ว`, + body: `${p.actor} แชร์รูปภาพ ${p.count} รูปใน "${p.trip}"`, + }), + collab_message: (p) => ({ + title: `ข้อความใหม่ใน "${p.trip}"`, + body: `${p.actor}: ${p.preview}`, + }), + packing_tagged: (p) => ({ + title: `รายการจัดกระเป๋า: ${p.category}`, + body: `${p.actor} มอบหมายหมวดหมู่รายการจัดกระเป๋า "${p.category}" ให้คุณใน "${p.trip}"`, + }), + version_available: (p) => ({ + title: 'มี TREK เวอร์ชันใหม่', + body: `TREK ${p.version} พร้อมใช้งานแล้ว ไปที่แผงผู้ดูแลระบบเพื่ออัปเดต`, + }), + replica_failure: (p) => ({ + title: 'การจำลองที่เก็บข้อมูลล้มเหลว', + body: + `การเขียนไปยังแบบจำลอง '${p.backend}' ล้มเหลว: ${p.op} ของ ${p.key} — ${p.error}.` + + (p.suppressed !== '0' ? ` มีการระงับข้อผิดพลาดเพิ่มเติม ${p.suppressed} รายการตั้งแต่การแจ้งเตือนครั้งก่อน` : ''), + }), + synology_session_cleared: () => ({ + title: 'ล้างเซสชัน Synology แล้ว', + body: 'บัญชีหรือ URL ของ Synology เปลี่ยนแปลง คุณจึงออกจากระบบ Synology Photos แล้ว', + }), + plugin_notification: (p) => ({ title: p.title ?? '', body: p.body ?? '' }), + }, + passwordReset: { + subject: 'รีเซ็ตรหัสผ่านของคุณ', + greeting: 'สวัสดี', + body: 'เราได้รับคำขอรีเซ็ตรหัสผ่านสำหรับบัญชี TREK ของคุณ คลิกปุ่มด้านล่างเพื่อตั้งรหัสผ่านใหม่', + ctaIntro: 'รีเซ็ตรหัสผ่าน', + expiry: 'ลิงก์นี้จะหมดอายุใน 60 นาที', + ignore: 'หากคุณไม่ได้ส่งคำขอนี้ คุณสามารถละเว้นอีเมลนี้ได้อย่างปลอดภัย — รหัสผ่านของคุณจะไม่เปลี่ยนแปลง', + }, +}; + +export default th; diff --git a/shared/src/i18n/th/files.ts b/shared/src/i18n/th/files.ts new file mode 100644 index 000000000..48bf31e2e --- /dev/null +++ b/shared/src/i18n/th/files.ts @@ -0,0 +1,66 @@ +import type { TranslationStrings } from '../types'; + +const files: TranslationStrings = { + 'files.filterStarred': "ติดดาว", + 'files.link': "ลิงก์", + 'files.linkTitle': "ลิงก์ไฟล์", + 'files.linkEmpty': "ยังไม่มีสถานที่หรือการจองที่จะลิงก์", + 'files.menu': "ตัวเลือกเพิ่มเติม", + 'files.uploadErrorSize': "ไฟล์มีขนาดใหญ่เกินไป (สูงสุด 50 MB)", + 'files.title': "ไฟล์", + 'files.pageTitle': "ไฟล์และเอกสาร", + 'files.subtitle': "{count} ไฟล์สำหรับ {trip}", + 'files.download': "ดาวน์โหลด", + 'files.openError': "ไม่สามารถเปิดไฟล์ได้", + 'files.downloadPdf': "ดาวน์โหลดไฟล์ PDF", + 'files.count': "{count} ไฟล์", + 'files.countSingular': "1 ไฟล์", + 'files.uploaded': "{count} อัปโหลดแล้ว", + 'files.uploadError': "การอัปโหลดล้มเหลว", + 'files.uploadErrorType': "ไม่รองรับไฟล์ประเภทนี้", + 'files.dropzone': "วางไฟล์ที่นี่", + 'files.dropzoneHint': "หรือคลิกเพื่อเรียกดู", + 'files.allowedTypes': "รูปภาพ, PDF, DOC, DOCX, XLS, XLSX, TXT, CSV · สูงสุด 50 MB", + 'files.uploading': "กำลังอัปโหลด...", + 'files.filterAll': "ทั้งหมด", + 'files.filterPdf': "PDF", + 'files.filterImages': "รูปภาพ", + 'files.filterDocs': "เอกสาร", + 'files.filterCollab': "หมายเหตุการทำงานร่วมกัน", + 'files.sourceCollab': "จากบันทึกการทำงานร่วมกัน", + 'files.empty': "ยังไม่มีไฟล์", + 'files.emptyHint': "อัปโหลดไฟล์เพื่อแนบไปกับการเดินทางของคุณ", + 'files.openTab': "เปิดในแท็บใหม่", + 'files.confirm.delete': "คุณแน่ใจหรือไม่ว่าต้องการลบไฟล์นี้", + 'files.toast.deleted': "ลบไฟล์แล้ว", + 'files.toast.deleteError': "ไม่สามารถลบไฟล์ได้", + 'files.sourcePlan': "แผนรายวัน", + 'files.sourceBooking': "การจอง", + 'files.sourceTransport': "ขนส่ง", + '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.assignTransport': "ขนส่ง", + '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': "เพิ่มบันทึก...", +}; +export default files; diff --git a/shared/src/i18n/th/help.ts b/shared/src/i18n/th/help.ts new file mode 100644 index 000000000..1a90d4343 --- /dev/null +++ b/shared/src/i18n/th/help.ts @@ -0,0 +1,12 @@ +import type { TranslationStrings } from '../types'; + +const help: TranslationStrings = { + 'help.title': "ช่วยเหลือและเอกสาร", + 'help.search': "ค้นหาเอกสาร...", + 'help.contents': "สารบัญ", + 'help.noResults': "ไม่มีหน้าที่ตรงกัน", + 'help.errorTitle': "ไม่สามารถโหลดหน้านี้ได้", + 'help.errorBody': "เนื้อหาความช่วยเหลือดึงมาจากวิกิ TREK ตรวจสอบการเชื่อมต่อของคุณแล้วลองอีกครั้ง", +}; + +export default help; diff --git a/shared/src/i18n/th/index.ts b/shared/src/i18n/th/index.ts new file mode 100644 index 000000000..db258024f --- /dev/null +++ b/shared/src/i18n/th/index.ts @@ -0,0 +1,112 @@ +import admin from './admin'; +import airport from './airport'; +import atlas from './atlas'; +import backup from './backup'; +import budget from './budget'; +import categories from './categories'; +import collab from './collab'; +import collection from './collection'; +import common from './common'; +import dashboard from './dashboard'; +import dawarich from './dawarich'; +import day from './day'; +import dayplan from './dayplan'; +import files from './files'; +import help from './help'; +import inspector from './inspector'; +import journey from './journey'; +import login from './login'; +import map from './map'; +import members from './members'; +import memories from './memories'; +import mobileAdmin from './mobileAdmin'; +import mobileAtlas from './mobileAtlas'; +import mobileCollections from './mobileCollections'; +import mobileJourney from './mobileJourney'; +import mobileNav from './mobileNav'; +import mobileSettings from './mobileSettings'; +import mobileTrip from './mobileTrip'; +import mobileVacay from './mobileVacay'; +import nav from './nav'; +import notif from './notif'; +import notifications from './notifications'; +import oauth from './oauth'; +import packing from './packing'; +import pdf from './pdf'; +import perm from './perm'; +import photos from './photos'; +import places from './places'; +import planner from './planner'; +import register from './register'; +import roadtrip from './roadtrip'; +import reservations from './reservations'; +import settings from './settings'; +import share from './share'; +import shared from './shared'; +import stats from './stats'; +import storage from './storage'; +import system_notice from './system_notice'; +import todo from './todo'; +import transport from './transport'; +import trip from './trip'; +import trips from './trips'; +import undo from './undo'; +import vacay from './vacay'; + +const locale = { + ...common, + ...trips, + ...nav, + ...dashboard, + ...roadtrip, + ...settings, + ...admin, + ...dayplan, + ...share, + ...shared, + ...login, + ...register, + ...vacay, + ...collection, + ...atlas, + ...trip, + ...places, + ...inspector, + ...reservations, + ...airport, + ...map, + ...budget, + ...files, + ...packing, + ...members, + ...categories, + ...backup, + ...photos, + ...pdf, + ...planner, + ...stats, + ...day, + ...memories, + ...collab, + ...perm, + ...undo, + ...notifications, + ...todo, + ...notif, + ...journey, + ...oauth, + ...system_notice, + ...transport, + ...help, + ...mobileTrip, + ...mobileJourney, + ...mobileVacay, + ...mobileAtlas, + ...mobileNav, + ...mobileAdmin, + ...mobileSettings, + ...mobileCollections, + ...storage, + ...dawarich, +}; +export default locale; diff --git a/shared/src/i18n/th/inspector.ts b/shared/src/i18n/th/inspector.ts new file mode 100644 index 000000000..f9c79b36b --- /dev/null +++ b/shared/src/i18n/th/inspector.ts @@ -0,0 +1,30 @@ +import type { TranslationStrings } from '../types'; + +const inspector: TranslationStrings = { + 'inspector.opened': "เปิด", + 'inspector.closed': "ปิดแล้ว", + 'inspector.openingHours': "เวลาทำการ", + 'inspector.showHours': "แสดงเวลาเปิดทำการ", + 'inspector.files': "ไฟล์", + 'inspector.filesCount': "{count} ไฟล์", + 'inspector.remove': "ลบ", + 'inspector.removeFromDay': "ลบออกจากวัน", + 'inspector.addToDay': "เพิ่มไปยังวัน", + 'inspector.confirmedRes': "ยืนยันการจองแล้ว", + 'inspector.pendingRes': "อยู่ระหว่างดำเนินการจอง", + 'inspector.google': "Google แผนที่", + 'inspector.navigation': "การนำทาง", + 'inspector.openWith': "เปิดด้วย", + 'inspector.openStreetMap': "OpenStreetMap", + 'inspector.website': "เปิดเว็บไซต์", + 'inspector.saveToCollection': "บันทึกลงคอลเลกชัน", + 'inspector.savedToCollection': "บันทึกแล้ว", + 'inspector.addRes': "เพิ่มการจอง", + 'inspector.editRes': "แก้ไขการจอง", + 'inspector.participants': "ผู้เข้าร่วม", + 'inspector.trackStats': "ติดตามสถิติ", + 'inspector.trackColor': "ติดตามสี", + 'inspector.trackColorAuto': "สีอัตโนมัติ", + 'inspector.trackColorCustom': "เลือกสีที่กำหนดเอง", +}; +export default inspector; diff --git a/shared/src/i18n/th/journey.ts b/shared/src/i18n/th/journey.ts new file mode 100644 index 000000000..9f65860d9 --- /dev/null +++ b/shared/src/i18n/th/journey.ts @@ -0,0 +1,646 @@ +import type { TranslationStrings } from '../types'; + +const journey: TranslationStrings = { + '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.subtitle': "เปลี่ยนการเดินทางของคุณให้เป็นเรื่องราวที่คุณจะไม่มีวันลืม", + 'journey.frontpage.createJourney': "สร้างการเดินทาง", + 'journey.frontpage.activeJourney': "การเดินทางที่กำลังใช้งานอยู่", + 'journey.frontpage.latestJourney': "การเดินทางล่าสุด", + '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.backToJourney': "กลับสู่การเดินทาง", + 'journey.detail.syncedWithTrips': "ซิงค์กับการเดินทาง", + 'journey.detail.addEntry': "เพิ่มรายการ", + 'journey.detail.jumpToTop': "กลับไปด้านบน", + 'journey.detail.jumpToLast': "ข้ามไปยังรายการสุดท้าย", + '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.stats.days': "วัน", + 'journey.stats.cities': "เมือง", + 'journey.stats.entries': "รายการ", + 'journey.stats.photos': "ภาพถ่าย", + 'journey.stats.places': "สถานที่", + 'journey.skeletons.show': "แสดงข้อเสนอแนะ", + 'journey.skeletons.hide': "ซ่อนข้อเสนอแนะ", + 'journey.verdict.lovedIt': "ชอบมันมาก", + 'journey.verdict.couldBeBetter': "อาจจะดีกว่านี้", + 'journey.synced.places': "สถานที่", + 'journey.synced.synced': "ซิงค์แล้ว", + 'journey.editor.discardChangesConfirm': "คุณมีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก ทิ้งมันไปเหรอ?", + 'journey.editor.uploadFailed': "การอัปโหลดรูปภาพล้มเหลว", + 'journey.editor.uploadPhotos': "อัปโหลดรูปภาพ", + 'journey.editor.uploading': "กำลังอัปโหลด...", + 'journey.editor.uploadingProgress': "กำลังอัปโหลด {done}/{total}...", + 'journey.editor.uploadPartialFailed': "{failed} จาก {total} รูปภาพล้มเหลว — บันทึกอีกครั้งเพื่อลองอีกครั้ง", + 'journey.editor.fromGallery': "จากแกลเลอรี", + 'journey.editor.allPhotosAdded': "เพิ่มรูปภาพทั้งหมดแล้ว", + 'journey.editor.externalPhotos': "ภาพถ่ายภายนอก", + 'journey.editor.externalPhotosFor': "รูปภาพสำหรับ {date}", + 'journey.editor.externalPhotosNearby': "รูปภาพใกล้เคียงก่อน", + 'journey.editor.externalPhotosNoLocation': "รูปภาพทั้งหมดของวันนี้", + 'journey.editor.externalPhotosQueued': "เข้าคิว", + 'journey.editor.externalPhotosUnavailable': "ไม่มีผู้ให้บริการภาพถ่ายที่เชื่อมต่ออยู่", + 'journey.editor.externalPhotosPartialFailed': "{failed} กลุ่มรูปภาพล้มเหลว — บันทึกอีกครั้งเพื่อลองอีกครั้ง", + '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.editor.useCurrentLocation': "ใช้ตำแหน่งปัจจุบันของฉัน", + 'journey.editor.locationPermissionDenied': + "การเข้าถึงตำแหน่งถูกปฏิเสธ อนุญาตในการตั้งค่าเบราว์เซอร์ของคุณแล้วลองอีกครั้ง", + 'journey.editor.locationTimeout': "หมดเวลารับตำแหน่งของคุณ ลองอีกครั้ง", + 'journey.editor.locationUnavailable': "ไม่สามารถระบุตำแหน่งของคุณได้", + 'journey.editor.locationInsecureContext': "ตำแหน่งต้องมีการเชื่อมต่อที่ปลอดภัย (HTTPS)", + 'journey.mood.amazing': "น่าทึ่งมาก", + 'journey.mood.good': "ดี", + 'journey.mood.neutral': "เป็นกลาง", + 'journey.mood.rough': "หยาบ", + 'journey.weather.sunny': "ซันนี่", + 'journey.weather.partly': "มีเมฆเป็นบางส่วน", + 'journey.weather.cloudy': "มีเมฆมาก", + 'journey.weather.rainy': "ฝนตก", + 'journey.weather.stormy': "มีพายุ", + 'journey.weather.cold': "เต็มไปด้วยหิมะ", + '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.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.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.role': "บทบาท", + 'journey.invite.viewer': "ผู้ดู", + 'journey.invite.editor': "บรรณาธิการ", + 'journey.invite.invite': "เชิญ", + 'journey.invite.inviting': "กำลังเชิญ...", + 'journey.settings.title': "การตั้งค่าการเดินทาง", + 'journey.settings.coverImage': "ภาพปก", + 'journey.settings.changeCover': "เปลี่ยนปก", + 'journey.settings.addCover': "เพิ่มภาพหน้าปก", + 'journey.settings.name': "ชื่อ", + 'journey.settings.subtitle': "คำบรรยาย", + 'journey.settings.subtitlePlaceholder': "เช่น ไทย เวียดนาม และกัมพูชา", + 'journey.settings.tracks': "เส้นทาง GPX", + 'journey.settings.showTripTracks': "แสดงเส้นทาง GPX ของการเดินทางทั้งหมด", + 'journey.settings.showTripTracksHint': "วาดเส้นทางที่บันทึกไว้จากการเดินทางที่เชื่อมโยงบนแผนที่", + 'journey.settings.endJourney': "ปิดการเดินทาง", + 'journey.settings.reopenJourney': "เปิดการเดินทางอีกครั้ง", + 'journey.settings.archived': "เก็บถาวรการเดินทางแล้ว", + 'journey.settings.reopened': "การเดินทางเปิดอีกครั้ง", + 'journey.settings.endDescription': "ซ่อนป้ายสด คุณสามารถเปิดใหม่ได้ตลอดเวลา", + '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.photosUploadFailed': "รูปภาพบางรูปไม่สามารถอัปโหลดได้", + 'journey.photosAdded': "เพิ่มรูปภาพ {count} แล้ว", + 'journey.public.notFound': "ไม่พบ", + 'journey.public.notFoundMessage': "ไม่มีการเดินทางนี้หรือลิงก์หมดอายุแล้ว", + 'journey.public.readOnly': "อ่านอย่างเดียว · การเดินทางสาธารณะ", + 'journey.public.tagline': "ชุดทรัพยากรการเดินทางและการสำรวจ", + 'journey.public.sharedVia': "แชร์ผ่าน", + 'journey.public.madeWith': "ทำด้วย", + 'journey.pdf.journeyBook': "หนังสือการเดินทาง", + 'journey.pdf.madeWith': "ทำด้วย TREK", + 'journey.pdf.day': "วัน", + 'journey.pdf.theEnd': "จุดจบ", + 'journey.pdf.saveAsPdf': "บันทึกเป็น PDF", + 'journey.pdf.pages': "หน้า", + 'journey.picker.tripPeriod': "ระยะเวลาการเดินทาง", + 'journey.picker.day': "วันนี้", + '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': "ค้นหา", + 'journey.studio.title': "เทรค สตูดิโอ", + 'journey.studio.open': "สตูดิโอ", + 'journey.studio.openAria': "เปิดสตูดิโอสมุดภาพ", + 'journey.studio.backToJourney': "กลับสู่การเดินทาง", + 'journey.studio.format': "รูปแบบหน้า", + 'journey.studio.formatA4Landscape': "แนวนอน A4", + 'journey.studio.formatA4Portrait': "แนวตั้ง A4", + 'journey.studio.formatSquare21': "สี่เหลี่ยมจัตุรัส 21 × 21 ซม", + 'journey.studio.formatSquare30': "สี่เหลี่ยมจัตุรัส 30 × 30 ซม", + 'journey.studio.pages': "หน้า", + 'journey.studio.cover': "ปก", + 'journey.studio.inspector': "คุณสมบัติ", + 'journey.studio.inspectorEmpty': "เลือกบางอย่างบนเพจเพื่อแก้ไข", + 'journey.studio.emptySpread': "สเปรดนี้ยังคงว่างเปล่า", + 'journey.studio.autoLayout': "เค้าโครงอัตโนมัติ", + 'journey.studio.export': "ส่งออก", + 'journey.studio.day': "วัน", + 'journey.studio.stations': "สถานี", + 'journey.studio.peersHere': "ที่นี่", + 'journey.studio.folioAuto': "อัตโนมัติ", + 'journey.studio.exportLayout': "เค้าโครง", + 'journey.studio.exportPages': "หน้าเดียว", + 'journey.studio.exportPagesHint': "แผ่นละ 1 ใบ ตามลำดับการอ่าน สิ่งที่เครื่องพิมพ์ต้องการ", + 'journey.studio.exportSpreads': "สเปรด", + 'journey.studio.exportSpreadsHint': "ครั้งละสองหน้าตามวิธีเปิดหนังสือ สำหรับการอ่าน", + 'journey.studio.exportFinishing': "จบ", + 'journey.studio.exportMarks': "เครื่องหมายครอบตัด", + 'journey.studio.exportMarksHint': "เพิ่มระยะตัดตก {bleed} มม. ทุกขอบ และแสดงเครื่องหมายตัด", + 'journey.studio.exportNote': "{sheets} แผ่นที่ {width} × {height} มม. เบราว์เซอร์ของคุณเปลี่ยนมุมมองการพิมพ์เป็น PDF", + 'journey.studio.exportOpen': "มุมมองการพิมพ์", + 'journey.studio.exportSave': "บันทึกเป็น PDF", + 'journey.studio.exportPreparing': "กำลังเตรียมตัว", + 'journey.studio.exportSheetCount': "{count} แผ่น", + 'journey.studio.undo': "เลิกทำ", + 'journey.studio.redo': "ทำซ้ำ", + 'journey.studio.zoomIn': "ซูมเข้า", + 'journey.studio.zoomOut': "ซูมออก", + 'journey.studio.zoomFit': "พอดีจะดู.", + 'journey.studio.downloadSpread': "ดาวน์โหลดสเปรดนี้", + 'journey.studio.downloadSpreadHint': "บันทึกการออกแบบของสเปรดนี้เป็นไฟล์ โดยไม่มีรูปถ่าย เพื่อแบ่งปันหรือนำมาใช้ซ้ำ", + 'journey.studio.importSpread': "นำเข้า", + 'journey.studio.importSpreadHint': "เพิ่มสเปรดจากไฟล์ออกแบบที่ดาวน์โหลด", + 'journey.studio.importSpreadFailed': "ไฟล์นั้นไม่ใช่สเปรด TREK Studio", + 'journey.studio.desktopOnly': "สตูดิโอต้องการหน้าจอที่ใหญ่กว่า", + 'journey.studio.desktopOnlyHint': "การออกแบบหนังสือต้องใช้พื้นที่ในการทำงาน ดังนั้น Studio และการสร้าง PDF จึงใช้งานได้เฉพาะบนเดสก์ท็อป ส่วนฟีเจอร์อื่นๆ ของการเดินทางยังใช้งานได้ตามปกติที่นี่", + 'journey.studio.formatA5Landscape': "A5 ภูมิทัศน์", + 'journey.studio.bookView': "มุมมองหนังสือ", + 'journey.studio.multiple': "หลาย", + 'journey.studio.kind.photo': "ภาพถ่าย", + 'journey.studio.kind.text': "ข้อความ", + 'journey.studio.kind.shape': "รูปร่าง", + 'journey.studio.position': "ตำแหน่ง", + 'journey.studio.width': "ว", + 'journey.studio.height': "ฮ", + 'journey.studio.text': "ข้อความ", + 'journey.studio.typography': "ประเภท", + 'journey.studio.leading': "เส้น", + 'journey.studio.colour': "สี", + 'journey.studio.autoColour': "อัตโนมัติ", + 'journey.studio.countryNames': "ชื่อ", + 'journey.studio.crop': "ครอบตัด", + 'journey.studio.look': "ดูสิ", + 'journey.studio.radius': "มุม", + 'journey.studio.shape': "รูปร่าง", + 'journey.studio.arrange': "จัดเรียง", + 'journey.studio.toFront': "นำมาไว้ข้างหน้า", + 'journey.studio.forward': "นำมาข้างหน้า", + 'journey.studio.backward': "ส่งกลับครับ", + 'journey.studio.toBack': "ส่งกลับครับ", + 'journey.studio.lock': "ล็อค", + 'journey.studio.unlock': "ปลดล็อค", + 'journey.studio.delete': "ลบ", + 'journey.studio.pageHint': "หน้า", + 'journey.studio.boundHint': "ติดตามรายการบันทึกประจำวัน การแก้ไขที่นี่จะทำให้ลิงก์นั้นเสียหาย", + 'journey.studio.fit.cover': "เติม", + 'journey.studio.fit.contain': "พอดี", + 'journey.studio.filter.none': "ต้นฉบับ", + 'journey.studio.filter.bw': "ขาวดำ", + 'journey.studio.filter.warm': "อบอุ่น", + 'journey.studio.shapeKind.rect': "สี่เหลี่ยมผืนผ้า", + 'journey.studio.shapeKind.ellipse': "วงรี", + 'journey.studio.focalHint': "ลากจุดเพื่อเลือกสิ่งที่อยู่ในเฟรม", + 'journey.studio.backCover': "ฝาหลัง", + 'journey.studio.sections': "ส่วนต่างๆ", + 'journey.studio.content': "เนื้อหา", + 'journey.studio.elements': "องค์ประกอบ", + 'journey.studio.templates': "เค้าโครง", + 'journey.studio.photos': "ภาพถ่าย", + 'journey.studio.entries': "รายการ", + 'journey.studio.addToPage': "เพิ่มลงในหน้านี้", + 'journey.studio.noPhotos': "การเดินทางครั้งนี้ยังไม่มีรูปถ่าย", + 'journey.studio.untitled': "ไม่มีชื่อ", + 'journey.studio.addTitle': "ชื่อเรื่อง", + 'journey.studio.addStory': "เรื่องราว", + 'journey.studio.addPlace': "สถานที่", + 'journey.studio.shapes': "รูปร่าง", + 'journey.studio.frames': "เฟรม", + 'journey.studio.emptyFrame': "กรอบเปล่า", + 'journey.studio.frameHint': "กรอบว่างจะทำเครื่องหมายว่ารูปภาพจะไปที่ใด วางหนึ่งรายการจากเนื้อหา", + 'journey.studio.shapeKind.line': "เส้น", + 'journey.studio.styleTitle': "หัวเรื่อง", + 'journey.studio.styleSubtitle': "หัวเรื่องย่อย", + 'journey.studio.styleBody': "ข้อความเนื้อหา", + 'journey.studio.styleCaption': "คำบรรยายภาพ", + 'journey.studio.sampleHeading': "หัวเรื่อง", + 'journey.studio.sampleSubheading': "หัวข้อย่อย", + 'journey.studio.sampleBody': "เขียนอะไรบางอย่างเกี่ยวกับวันนี้", + 'journey.studio.sampleCaption': "คำบรรยายภาพ", + 'journey.studio.templatesCoverHint': "เค้าโครงใช้กับสเปรดด้านใน ปกและด้านหลังได้รับการออกแบบด้วยตัวมันเอง", + 'journey.studio.tpl.heroStory': "ฮีโร่และเรื่องราว", + 'journey.studio.tpl.fullBleed': "รูปเดียวกระจายเต็มเลย", + 'journey.studio.tpl.twoUp': "สองหน้าเต็ม.", + 'journey.studio.tpl.grid4': "สี่ขึ้น", + 'journey.studio.tpl.grid6': "หกขึ้น", + 'journey.studio.tpl.strip': "แถบและข้อความ", + 'journey.studio.tpl.quietText': "ข้อความเท่านั้น", + 'journey.studio.tpl.portraitPair': "คู่", + 'journey.studio.dropPhotoHere': "ลากและวาง\nรูปภาพของคุณ", + 'journey.studio.searchContent': "ค้นหาภาพถ่ายและรายการ", + 'journey.studio.noMatches': "ไม่มีอะไรตรงกับสิ่งนั้น", + 'journey.studio.decorations': "ตกแต่ง", + 'journey.studio.quoteMark': "เครื่องหมายคำพูด", + 'journey.studio.circleOutline': "วงกลมที่สรุปไว้", + 'journey.studio.roundFrame': "กรอบโค้งมน", + 'journey.studio.shapeKind.rounded': "สี่เหลี่ยมผืนผ้าโค้งมน", + 'journey.studio.shapeKind.triangle': "สามเหลี่ยม", + 'journey.studio.shapeKind.outline': "โครงร่างเท่านั้น", + 'journey.studio.travel': "การเดินทาง", + 'journey.studio.travelEmpty': "ตัวเลขจากการเดินทางครั้งนี้ยังไม่พร้อม", + 'journey.studio.grids': "กริด", + 'journey.studio.gridHint': "ตารางจะปล่อยบล็อกของเฟรมว่าง ลากรูปภาพมาไว้บนรูปภาพจากเนื้อหา", + 'journey.studio.lines': "เส้น", + 'journey.studio.frameStyles': "รูปแบบของเฟรม", + 'journey.studio.frameShapes': "รูปร่างกรอบ", + 'journey.studio.plainFrame': "ธรรมดา", + 'journey.studio.polaroidFrame': "โพลารอยด์", + 'journey.studio.whiteFrame': "ขอบสีขาว", + 'journey.studio.shadowFrame': "เงาตก", + 'journey.studio.filmFrame': "ฟิล์ม", + 'journey.studio.tapeFrame': "อัดเทปแล้ว", + 'journey.studio.shapeGroup.basic': "ขั้นพื้นฐาน", + 'journey.studio.shapeGroup.polygons': "รูปหลายเหลี่ยม", + 'journey.studio.shapeGroup.stars': "ดาว", + 'journey.studio.shapeGroup.arrows': "ลูกศร", + 'journey.studio.shapeGroup.speech': "คำพูด", + 'journey.studio.shapeGroup.travel': "การเดินทาง", + 'journey.studio.shapeGroup.decor': "ตกแต่ง", + 'journey.studio.shapeGroup.banners': "แบนเนอร์", + 'journey.studio.summary': "สรุป", + 'journey.studio.tripSummary': "สรุปการเดินทาง", + 'journey.studio.statsRow': "หนึ่งแถว", + 'journey.studio.statsFull': "ทุกอย่าง", + 'journey.studio.routeMap': "แผนที่เส้นทาง", + 'journey.studio.mapStyle.minimal': "น้อยที่สุด", + 'journey.studio.mapStyle.outline': "โครงร่าง", + 'journey.studio.mapStyle.paper': "กระดาษ", + 'journey.studio.mapStyle.dark': "มืด", + 'journey.studio.countries': "ประเทศต่างๆ", + 'journey.studio.countryList': "รายชื่อประเทศ", + 'journey.studio.countryGrid': "ตารางประเทศ", + 'journey.studio.noCountries': "ยังไม่มีประเทศใดที่ดำเนินการสำหรับการเดินทางครั้งนี้", + 'journey.studio.noRoute': "ยังไม่มีจุดจอดพร้อมพิกัด", + 'journey.studio.marks': "เครื่องหมาย", + 'journey.studio.dateMark': "วันที่", + 'journey.studio.dayMark': "เคาน์เตอร์วัน", + 'journey.studio.dayWord': "วัน", + 'journey.studio.coordsMark': "พิกัด", + 'journey.studio.coordsDms': "องศา", + 'journey.studio.coordsDecimal': "ทศนิยม", + 'journey.studio.flagMark': "ธง", + 'journey.studio.distanceMark': "ระยะทาง", + 'journey.studio.metric.distance': "ระยะทาง", + 'journey.studio.metric.days': "วัน", + 'journey.studio.metric.steps': "ขั้นตอน", + 'journey.studio.metric.photos': "ภาพถ่าย", + 'journey.studio.metric.countries': "ประเทศต่างๆ", + 'journey.studio.metric.places': "สถานที่", + 'journey.studio.metric.furthest': "ไกลที่สุด", + 'journey.studio.kind.map': "แผนที่", + 'journey.studio.kind.stats': "ตัวเลข", + 'journey.studio.kind.countries': "ประเทศต่างๆ", + 'journey.studio.kind.badge': "มาร์ค", + 'journey.studio.kind.list': "รายการ", + 'journey.studio.kind.icon': "ไอคอน", + 'journey.studio.duplicate': "ทำซ้ำ", + 'journey.studio.style': "สไตล์", + 'journey.studio.shows': "การแสดง", + 'journey.studio.size': "ขนาด", + 'journey.studio.weight': "น้ำหนัก", + 'journey.studio.italic': "ตัวเอียง", + 'journey.studio.tracking': "การติดตาม", + 'journey.studio.rotation': "การหมุน", + 'journey.studio.opacity': "ความทึบ", + 'journey.studio.fill': "เติม", + 'journey.studio.fillOn': "อิ่มแล้ว", + 'journey.studio.stroke': "โครงร่าง", + 'journey.studio.strokeWidth': "ความกว้าง", + 'journey.studio.gradient': "จางลง", + 'journey.studio.gradientDown': "ลง", + 'journey.studio.gradientUp': "ขึ้นไป", + 'journey.studio.showIcons': "ไอคอน", + 'journey.studio.mapFit': "พอดี", + 'journey.studio.mapPadding': "ห้อง", + 'journey.studio.mapShape': "รูปร่าง", + 'journey.studio.align.left': "ซ้าย", + 'journey.studio.align.center': "ศูนย์", + 'journey.studio.align.right': "ถูกต้อง", + 'journey.studio.markStyle.plain': "ธรรมดา", + 'journey.studio.markStyle.chip': "ชิป", + 'journey.studio.markStyle.outline': "โครงร่าง", + 'journey.studio.markStyle.stacked': "ซ้อนกัน", + 'journey.studio.icon': "ไอคอน", + 'journey.studio.iconAndLabel': "ไอคอนและข้อความ", + 'journey.studio.iconOnly': "ไอคอนเท่านั้น", + 'journey.studio.labelOnly': "ข้อความเท่านั้น", + 'journey.studio.icons': "ไอคอน", + 'journey.studio.iconsForTravel': "สำหรับการเดินทาง", + 'journey.studio.iconsAll': "ไอคอนทั้งหมด", + 'journey.studio.searchIcons': "ค้นหาไอคอน", + 'journey.studio.lineWidth': "ความหนา", + 'journey.studio.mask': "ตัดให้ได้รูปทรง", + 'journey.studio.maskNone': "ไม่มี", + 'journey.studio.frameStyle': "กรอบ", + 'journey.studio.mapLayers': "เลเยอร์", + 'journey.studio.showLand': "ประเทศต่างๆ", + 'journey.studio.showRoute': "เส้นทาง", + 'journey.studio.showPins': "จุดแวะ", + 'journey.studio.showLabels': "ป้ายกำกับ", + 'journey.studio.units': "หน่วย", + 'journey.studio.metrics': "ตัวเลข", + 'journey.studio.layout': "เค้าโครง", + 'journey.studio.layoutGrid': "กริด", + 'journey.studio.layoutRow': "แถว", + 'journey.studio.layoutColumn': "คอลัมน์", + 'journey.studio.layoutList': "รายการ", + 'journey.studio.showOutline': "โครงร่าง", + 'journey.studio.showFlag': "ธง", + 'journey.studio.showName': "ชื่อ", + 'journey.studio.textScale': "ขนาดข้อความ", + 'journey.studio.accent': "สีเน้น", + 'journey.studio.refresh': "อัปเดตจาก Journey", + 'journey.studio.staleHint': "Journey มีการเปลี่ยนแปลงตั้งแต่คำนวณสถิติเหล่านี้", + 'journey.studio.align': "จัดตำแหน่ง", + 'journey.studio.filter.cool': "โทนเย็น", + 'journey.studio.filter.fade': "จางลง", + 'journey.studio.filter.contrast': "สีสด", + 'journey.studio.strokeStyle': "รูปแบบเส้น", + 'journey.studio.strokeSolid': "เส้นทึบ", + 'journey.studio.strokeDashed': "ประ", + 'journey.studio.strokeDotted': "ลายจุด", + 'journey.studio.singleFigures': "ตัวเลขเดี่ยว", + 'journey.studio.addPage': "เพิ่มหน้าคู่", + 'journey.studio.addPageAfter': "แทรกหน้าคู่ต่อจากนี้", + 'journey.studio.duplicatePage': "ทำสำเนาหน้าคู่", + 'journey.studio.deletePage': "ลบสเปรด", + 'journey.studio.movePageUp': "ย้ายมาก่อน", + 'journey.studio.movePageDown': "ย้ายในภายหลัง", + 'journey.studio.beta': "เบต้า", + 'journey.studio.addProsCons': "ข้อดีข้อเสีย", + 'journey.studio.showMarks': "เครื่องหมาย", + 'journey.studio.formatCustom': "ขนาดที่กำหนดเอง", + 'journey.studio.document': "เอกสาร", + 'journey.studio.pageNumbers': "หมายเลขหน้า", + 'journey.studio.pageNumbersOn': "เปิด", + 'journey.studio.pageNumbersOff': "ปิด", + 'journey.studio.folio.outer': "ภายนอก", + 'journey.studio.folio.inner': "ภายใน", + 'journey.studio.folio.centre': "อยู่ตรงกลาง", + 'journey.studio.folioStart': "เริ่มต้นที่", + 'journey.studio.folioMargin': "ขอบ", + 'journey.studio.relayoutSpread': "หน้าคู่นี้", + 'journey.studio.relayoutSpreadHint': "สร้างใหม่จากรายการนี้", + 'journey.studio.relayoutSpreadNone': "หน้านี้ไม่ได้ถูกสร้างขึ้นจากรายการ", + 'journey.studio.relayoutBook': "หนังสือทั้งเล่ม", + 'journey.studio.relayoutBookHint': "แทนที่ทุกหน้า — เลิกทำได้", + 'journey.studio.tpl.coverFull': "เต็มขอบ", + 'journey.studio.tpl.coverBand': "ภาพและแถบสี", + 'journey.studio.tpl.coverWindow': "ใส่กรอบ", + 'journey.studio.tpl.coverQuiet': "ตัวอักษรเท่านั้น", + 'journey.studio.tpl.coverHalf': "สองซีก", + 'journey.studio.tpl.fullText': "ภาพและเรื่องราว", + 'journey.studio.tpl.grid9': "9 ภาพ", + 'journey.studio.tpl.mosaic': "โมเสก", + 'journey.studio.tpl.bandQuote': "คำระหว่าง", + 'journey.studio.tpl.staggerFour': "4 ภาพเหลื่อมกัน", + 'journey.studio.weightMissing': "แบบอักษรนี้ไม่ได้มีน้ำหนักขนาดนั้น", + 'journey.studio.mapSource': "แหล่งที่มาของแผนที่", + 'journey.studio.mapSourceVector': "โครงร่าง", + 'journey.studio.mapSourceRelief': "ภูมิประเทศ", + 'journey.studio.routeLook': "เส้น", + 'journey.studio.roads': "ถนน", + 'journey.studio.roadsFetch': "ไปตามถนน", + 'journey.studio.roadsFollow': "ถนน", + 'journey.studio.roadsDirect': "โดยตรง", + 'journey.studio.roadsAgain': "ดึงเส้นทางอีกครั้ง", + 'journey.studio.roadsClear': "ล้าง", + 'journey.studio.roadsBusy': "กำลังขอเส้นทาง", + 'journey.studio.roadsHint': "ขอเส้นทางที่ขับจริงในแต่ละช่วงจากบริการนำทาง ช่วงทางไกลจะคงเดิม", + 'journey.studio.roadsHave': "บันทึกเส้นทางไว้ในหนังสือแล้ว จึงพิมพ์เส้นทางเดิมได้แม้ออฟไลน์", + 'journey.studio.routeStyle': "สไตล์", + 'journey.studio.routePlain': "ธรรมดา", + 'journey.studio.routeDrawn': "วาด", + 'journey.studio.routeArc': "ช่วงทางไกล", + 'journey.studio.routeStraight': "ตรง", + 'journey.studio.routeBow': "เส้นโค้ง", + 'journey.studio.routeDashArcs': "ใช้เส้นประกับช่วงทางไกล", + 'journey.studio.mapStops': "จุดแวะ", + 'journey.studio.pinDot': "จุด", + 'journey.studio.pinPhoto': "ภาพถ่าย", + 'journey.studio.pinPhotoNone': "จุดแวะเหล่านี้ยังไม่มีรูปภาพ จึงแสดงเป็นจุด", + 'journey.studio.mapSourceSatellite': "ดาวเทียม", + 'journey.studio.recommended': "แนะนำ", + 'journey.studio.bleed': "ระยะตัดตก", + 'journey.studio.safeArea': "ปลอดภัย", + 'journey.studio.mapSourceSatelliteHint': "ภาพ Sentinel-2 ไร้เมฆ พิมพ์ได้ฟรีเมื่อระบุแหล่งที่มา และคมชัดถึงระดับถนนในเมือง", + 'journey.studio.mapPerTrip': "เที่ยวละครั้ง", + 'journey.studio.mapWholeJourney': "ทั้งการเดินทาง", + 'journey.studio.mapScope': "การแสดง", + 'journey.studio.mapPrintDpi': "พิมพ์เมื่อประมาณ", + 'journey.studio.mapPrintDpiLow': "ภาพจะไม่คมที่ขนาดนี้ ลองมุมมองที่กว้างขึ้นหรือใช้แหล่งอื่น", + 'journey.studio.mapSourceReliefHint': "ภาพนูนสีเทาของ NASA พิมพ์ได้ฟรี ดีที่สุดสำหรับประเทศหรือทวีป หยาบเกินไปสำหรับเมืองเดียว", + 'journey.studio.mapSourceTiles': "ไทล์แผนที่", + 'journey.studio.mapSourceStatic': "Mapbox", + 'journey.studio.mapSourceHint': "ดึงข้อมูลเมื่อเพจถูกแสดงผล และพิมพ์พร้อมเครดิต", + 'journey.studio.mapZoom': "ซูม", + 'journey.studio.mapFraming': "ดู", + 'journey.studio.mapFitStops': "จุดแวะ", + 'journey.studio.mapFitCountry': "ทั้งประเทศ", + 'journey.studio.mapPadTight': "แน่น", + 'journey.studio.mapPadNormal': "ปกติ", + 'journey.studio.mapPadWide': "กว้าง", + 'journey.studio.mapPadFar': "ไกล", + 'journey.studio.mapClipRect': "ในกล่อง", + 'journey.studio.mapClipCountry': "ตัดให้ได้รูปทรง", + 'journey.studio.mapClipNeedsCountry': "ต้องระบุประเทศเพื่อครอบตัดตามรูปทรง", + 'journey.studio.mapCutVector': "ตัดออก", + 'journey.studio.mapCutTiles': "แผนที่ตัดออก", + 'journey.studio.mapZoomAuto': "พอดี", + 'journey.studio.saving': "กำลังบันทึก", + 'journey.studio.saved': "บันทึกแล้ว", + 'journey.studio.saveFailed': "ไม่ได้บันทึก", + 'journey.studio.saveRetry': "ลองอีกครั้ง", + 'journey.studio.saveConflict': "มีคนอื่นบันทึกหนังสือเล่มนี้ไว้", + 'journey.studio.saveTakeTheirs': "เอาของพวกเขา", + 'journey.studio.saveKeepMine': "เก็บของฉันไว้", + 'journey.studio.rotate': "หมุน", + 'journey.studio.rotateLeft': "หมุนไปทางซ้าย", + 'journey.studio.rotateRight': "หมุนไปทางขวา", + 'journey.studio.saveReadOnly': "อ่านอย่างเดียว ไม่ได้บันทึก", + 'journey.studio.filterPhotos': "กรองรูปภาพ", + 'journey.studio.filterAll': "รูปภาพทั้งหมด", + 'journey.studio.filterLoose': "ไม่อยู่ในรายการ", + 'journey.studio.filterRecent': "เพิ่งอัปโหลด", + 'journey.studio.filterThisPage': "หน้านี้", + 'journey.studio.entryPhotos': "ภาพถ่าย", + 'journey.studio.noEntryPhotos': "รายการนี้ยังไม่มีรูปถ่าย", + 'journey.studio.noLoosePhotos': "ทุกภาพถ่ายที่นี่เป็นของรายการ", + 'journey.studio.uploadPhotos': "อัปโหลดรูปภาพ", + 'journey.studio.uploadHint': "วางรูปภาพที่นี่ หรือคลิกเพื่อเลือกบางส่วน", + 'journey.studio.uploadToEntry': "รูปภาพใหม่จะเข้าสู่รายการนี้", + 'journey.studio.uploadToGallery': "รูปภาพใหม่จะเข้าสู่แกลเลอรี่", + 'journey.studio.uploading': "กำลังอัปโหลด {done} จาก {total}", + 'journey.studio.dropFilesHere': "วางเพื่อเพิ่มรูปภาพ", + 'journey.studio.videosSkipped': "ไม่รวมวิดีโอ {count} รายการ เนื่องจากหนังสือรองรับเฉพาะรูปภาพ", + 'journey.studio.fillPage': "เติมหน้า", + 'journey.studio.fillSpread': "เติมสเปรด", + 'journey.studio.fillHint': + "ขยายรูปภาพให้ทั่วทั้งหน้า รวมขอบตก และส่งไปด้านหลังสิ่งอื่นๆ", + 'journey.studio.stops': "จุดแวะ", + 'journey.studio.stopsHint': + "ทุกจุดแวะจะนับรวมเส้นทาง ระยะทาง และประเทศ ปิดสวิตช์เครื่องหนึ่งเพื่อทิ้งไว้ เช่น สนามบินที่บ้านของคุณ", + 'journey.studio.stopOn': "นับ", + 'journey.studio.stopOff': "ทิ้งไว้", + 'journey.studio.stopToggle': "นับจุดแวะนี้", + 'journey.studio.stopsFailed': "ไม่สามารถเปลี่ยนจุดแวะได้", + 'journey.editor.statsExcluded': "ให้ออกจากเส้นทาง", + 'journey.editor.statsExcludedHint': + "จุดแวะพักจะอยู่ในบันทึกแต่ไม่นับรวมระยะทาง ประเทศ หรือแผนที่ใน Studio", + 'journey.entry.offRoute': "นอกเส้นทาง", + 'journey.suggestions.dismiss': "ซ่อนคำแนะนำนี้", + 'journey.suggestions.dismissed': "ซ่อนคำแนะนำแล้ว", + 'journey.suggestions.restore': "เรียกคืนคำแนะนำที่ซ่อน", + 'journey.suggestions.restoreCount': "คำแนะนำที่ซ่อน ({count})", + 'journey.suggestions.restored': "เรียกคืนคำแนะนำ {count} รายการแล้ว", + 'journey.detail.addOnThisDay': "เพิ่มบันทึกในวันนี้", + 'journey.detail.jumpToDay': "ไปที่ {date}", + 'journey.detail.searchPlaceholder': "ค้นหาในบันทึกการเดินทางนี้", + 'journey.detail.searchEmpty': "ไม่มีบันทึกที่ตรงกับ “{query}”", + 'journey.settings.entryFields': "ฟิลด์ของบันทึก", + 'journey.settings.entryFieldsHint': "ปิดสิ่งที่บันทึกการเดินทางนี้ไม่ได้ใช้ ข้อมูลที่เขียนไว้แล้วจะไม่สูญหาย", + 'journey.settings.showVerdict': "ข้อดีและข้อเสีย", + 'journey.settings.showMood': "อารมณ์", + 'journey.settings.showWeather': "สภาพอากาศ", + 'journey.entry.suggestion': "คำแนะนำ", + 'journey.editor.addDetails': "+ รายละเอียด", +}; +export default journey; diff --git a/shared/src/i18n/th/login.ts b/shared/src/i18n/th/login.ts new file mode 100644 index 000000000..cad92332d --- /dev/null +++ b/shared/src/i18n/th/login.ts @@ -0,0 +1,76 @@ +import type { TranslationStrings } from '../types'; + +const login: TranslationStrings = { + 'login.error': "การเข้าสู่ระบบล้มเหลว กรุณาตรวจสอบข้อมูลประจำตัวของคุณ", + 'login.tagline': "การเดินทางของคุณ\nแผนของคุณ", + 'login.description': "วางแผนการเดินทางร่วมกันด้วยแผนที่เชิงโต้ตอบ งบประมาณ และการซิงค์แบบเรียลไทม์", + '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.rememberMe': "จำฉันไว้", + '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': "การรีเซ็ตล้มเหลว ลิงก์อาจหมดอายุแล้ว", + 'login.passkey.signIn': "เข้าสู่ระบบด้วยพาสคีย์", + 'login.passkey.failed': "การเข้าสู่ระบบด้วยพาสคีย์ล้มเหลว โปรดลองอีกครั้ง", + 'login.insecureCookie.title': "การเข้าสู่ระบบจะไม่ติดบน HTTP", + 'login.insecureCookie.body': + "คุณกำลังเชื่อมต่อผ่าน HTTP ธรรมดา ดังนั้นเบราว์เซอร์ของคุณจึงทิ้งคุกกี้เซสชันที่ปลอดภัยของ TREK คำขอถัดไปล้มเหลวด้วย \"ต้องใช้โทเค็นการเข้าถึง\" แก้ไข: ใช้ HTTPS หรือสำหรับชุดโฮมแล็บ COOKIE_SECURE=false", + 'login.insecureCookie.link': "เปิดคู่มือการแก้ไขปัญหา", +}; +export default login; diff --git a/shared/src/i18n/th/map.ts b/shared/src/i18n/th/map.ts new file mode 100644 index 000000000..5d470b50d --- /dev/null +++ b/shared/src/i18n/th/map.ts @@ -0,0 +1,30 @@ +import type { TranslationStrings } from '../types'; + +const map: TranslationStrings = { + 'map.connections': "การเชื่อมต่อ", + 'map.showConnections': "แสดงเส้นทางการจอง", + 'map.hideConnections': "ซ่อนเส้นทางการจอง", + 'poi.searchThisArea': "ค้นหาบริเวณนี้", + 'poi.cat.restaurants': "ร้านอาหาร", + 'poi.cat.cafes': "คาเฟ่", + 'poi.cat.bars': "บาร์และสถานบันเทิงยามค่ำคืน", + 'poi.cat.hotels': "ที่พัก", + 'poi.cat.sights': "สถานที่ท่องเที่ยว", + 'poi.cat.museums': "พิพิธภัณฑ์และวัฒนธรรม", + 'poi.cat.nature': "ธรรมชาติและอุทยาน", + 'poi.cat.activities': "กิจกรรม", + 'map.showAllConnections': "แสดงเส้นทางการจองทั้งหมด", + 'map.hideAllConnections': "ซ่อนเส้นทางการจองทั้งหมด", + 'map.baseLayer.default': "แผนที่", + 'map.baseLayer.satellite': "ดาวเทียม", + 'map.baseLayer.switchToSatellite': "สลับไปที่มุมมองดาวเทียม", + 'map.baseLayer.switchToDefault': "สลับไปที่มุมมองแผนที่", + 'map.location.denied': "การเข้าถึงตำแหน่งถูกบล็อก ตรวจสอบการตั้งค่าอุปกรณ์ของคุณ แอพที่ติดตั้งจะมีสิทธิ์เข้าถึงตำแหน่งของตัวเอง แยกจากเบราว์เซอร์", + 'map.location.unavailable': "ไม่สามารถระบุตำแหน่งของคุณได้", + 'map.location.timeout': "การค้นหาของคุณใช้เวลานานเกินไป ลองอีกครั้งด้วยมุมมองท้องฟ้าที่ชัดเจนยิ่งขึ้น", + 'map.overview.show': "แสดงทั้งทริป", + 'map.overview.hide': "ซ่อนทั้งทริป", + 'map.overview.total': "ระยะทางรวม", + 'map.attribution': "เครดิตแผนที่", +}; +export default map; diff --git a/shared/src/i18n/th/members.ts b/shared/src/i18n/th/members.ts new file mode 100644 index 000000000..6bf1de05d --- /dev/null +++ b/shared/src/i18n/th/members.ts @@ -0,0 +1,38 @@ +import type { TranslationStrings } from '../types'; + +const members: TranslationStrings = { + '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': "ลบไม่สำเร็จ", + 'members.makeOwner': "ตั้งเป็นเจ้าของ", + 'members.confirmTransfer': "โอนความเป็นเจ้าของไปที่ {name} หรือไม่ คุณจะกลายเป็นสมาชิกประจำ", + 'members.transferError': "ไม่สามารถโอนความเป็นเจ้าของได้", + 'members.guests': "แขก", + 'members.guest': "แขก", + 'members.guestsHint': + "คนไม่มีบัญชี. สามารถกำหนดให้กับต้นทุน การบรรจุ และงานได้ แต่ไม่สามารถลงชื่อเข้าใช้ได้", + 'members.addGuest': "เพิ่มแขก", + 'members.guestNamePlaceholder': "ชื่อแขก", + 'members.guestAdded': "เพิ่มแขกแล้ว", + 'members.guestAddError': "ไม่สามารถเพิ่มแขกได้", + 'members.guestRenameError': "เปลี่ยนชื่อแขกไม่สำเร็จ", + 'members.guestRemoved': "นำแขกออกแล้ว", + 'members.confirmRemoveGuest': "ลบแขกรายนี้ใช่ไหม การมอบหมายและส่วนแบ่งต้นทุนของพวกเขาจะถูกลบออกด้วย", +}; +export default members; diff --git a/shared/src/i18n/th/memories.ts b/shared/src/i18n/th/memories.ts new file mode 100644 index 000000000..c41da0c29 --- /dev/null +++ b/shared/src/i18n/th/memories.ts @@ -0,0 +1,75 @@ +import type { TranslationStrings } from '../types'; + +const memories: TranslationStrings = { + '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}", + 'memories.providerUrl': "URL ของเซิร์ฟเวอร์", + 'memories.providerApiKey': "คีย์ API", + 'memories.providerUsername': "ชื่อผู้ใช้", + 'memories.providerPassword': "รหัสผ่าน", + 'memories.providerOTP': "รหัส MFA (หากเปิดใช้งาน)", + 'memories.skipSSLVerification': "ข้ามการตรวจสอบใบรับรอง SSL", + 'memories.immichAutoUpload': "อัปโหลดรูปภาพการเดินทางไปยัง Immich โดยอัตโนมัติ", + 'memories.providerUrlHintSynology': "รวมเส้นทางแอป Photos ไว้ใน URL เช่น https://nas:5001/photo", + 'memories.testConnection': "ทดสอบการเชื่อมต่อ", + 'memories.testShort': "ทดสอบ", + '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': "กรุณากรอกข้อมูลในช่องที่ต้องกรอกทั้งหมด", +}; +export default memories; diff --git a/shared/src/i18n/th/mobileAdmin.ts b/shared/src/i18n/th/mobileAdmin.ts new file mode 100644 index 000000000..1f8c40eae --- /dev/null +++ b/shared/src/i18n/th/mobileAdmin.ts @@ -0,0 +1,9 @@ +import type { TranslationStrings } from '../types'; + +const mobileAdmin: TranslationStrings = { + 'mobileAdmin.create': "ผู้ใช้ใหม่", + 'mobileAdmin.updateAction': "อัปเดต", + 'mobileAdmin.updateLine': "เวอร์ชัน {version} พร้อมใช้งาน · คุณมี {current}", +}; + +export default mobileAdmin; diff --git a/shared/src/i18n/th/mobileAtlas.ts b/shared/src/i18n/th/mobileAtlas.ts new file mode 100644 index 000000000..1759b45ce --- /dev/null +++ b/shared/src/i18n/th/mobileAtlas.ts @@ -0,0 +1,8 @@ +import type { TranslationStrings } from '../types'; + +const mobileAtlas: TranslationStrings = { + 'mobileAtlas.visited': "เยี่ยมชมแล้ว", + 'mobileAtlas.planned': "วางแผนแล้ว", +}; + +export default mobileAtlas; diff --git a/shared/src/i18n/th/mobileCollections.ts b/shared/src/i18n/th/mobileCollections.ts new file mode 100644 index 000000000..1db15463c --- /dev/null +++ b/shared/src/i18n/th/mobileCollections.ts @@ -0,0 +1,7 @@ +import type { TranslationStrings } from '../types'; + +const mobileCollections: TranslationStrings = { + 'mobileCollections.status': "สถานะ", +}; + +export default mobileCollections; diff --git a/shared/src/i18n/th/mobileJourney.ts b/shared/src/i18n/th/mobileJourney.ts new file mode 100644 index 000000000..d639512d7 --- /dev/null +++ b/shared/src/i18n/th/mobileJourney.ts @@ -0,0 +1,17 @@ +import type { TranslationStrings } from '../types'; + +const mobileJourney: TranslationStrings = { + 'mobileJourney.latestJourney': "การเดินทางล่าสุด", + 'mobileJourney.otherJourneys': "การเดินทางอื่นๆ", + 'mobileJourney.entriesCount': "{count} รายการ", + 'mobileJourney.photosCount': "{count} รูปภาพ", + 'mobileJourney.placesCount': "{count} สถานที่", + 'mobileJourney.daysCount': "{count} วัน", + 'mobileJourney.time': "เวลา", + 'mobileJourney.tags': "แท็ก", + 'mobileJourney.addTag': "เพิ่มแท็ก", + 'mobileJourney.uploadFromDevice': "อัปโหลดจากอุปกรณ์", + 'mobileJourney.browseProvider': "เรียกดู {name}", +}; + +export default mobileJourney; diff --git a/shared/src/i18n/th/mobileNav.ts b/shared/src/i18n/th/mobileNav.ts new file mode 100644 index 000000000..c38f84d6e --- /dev/null +++ b/shared/src/i18n/th/mobileNav.ts @@ -0,0 +1,9 @@ +import type { TranslationStrings } from '../types'; + +const mobileNav: TranslationStrings = { + 'mobileNav.journeySub': "บันทึกการเดินทาง", + 'mobileNav.collectionsSub': "สถานที่ที่บันทึกไว้", + 'mobileNav.more': "เพิ่มเติม", +}; + +export default mobileNav; diff --git a/shared/src/i18n/th/mobileSettings.ts b/shared/src/i18n/th/mobileSettings.ts new file mode 100644 index 000000000..2a1a1841f --- /dev/null +++ b/shared/src/i18n/th/mobileSettings.ts @@ -0,0 +1,7 @@ +import type { TranslationStrings } from '../types'; + +const mobileSettings: TranslationStrings = { + 'mobileSettings.blurBookingCodesHint': "ซ่อนรหัสการจองจนกว่าคุณจะแตะเพื่อแสดง", +}; + +export default mobileSettings; diff --git a/shared/src/i18n/th/mobileTrip.ts b/shared/src/i18n/th/mobileTrip.ts new file mode 100644 index 000000000..d283d87be --- /dev/null +++ b/shared/src/i18n/th/mobileTrip.ts @@ -0,0 +1,69 @@ +import type { TranslationStrings } from '../types'; + +const mobileTrip: TranslationStrings = { + 'mobileTrip.addBookingShort': "การจอง", + 'mobileTrip.addNoteShort': "หมายเหตุ", + 'mobileTrip.addPlaceShort': "สถานที่", + 'mobileTrip.addToDayQuestion': "เพิ่มในวันใด?", + 'mobileTrip.addTransportShort': "ขนส่ง", + 'mobileTrip.allDays': "ทุกวัน", + 'mobileTrip.assignedDays': "วันที่ได้รับมอบหมาย", + 'mobileTrip.assignmentNotes': "บันทึกเฉพาะวัน", + 'mobileTrip.bookingsEmpty': "ยังไม่มีการจอง", + 'mobileTrip.collabFeatureDisabled': "คุณลักษณะนี้ถูกปิดใช้งานสำหรับการเดินทางครั้งนี้", + 'mobileTrip.compactView': "มุมมองที่กะทัดรัด", + 'mobileTrip.dayAnnounce': "วันที่ {current} จาก {total}", + 'mobileTrip.dayTitlePlaceholder': "ชื่อวัน", + 'mobileTrip.export': "ส่งออก", + 'mobileTrip.filesEmpty': "ยังไม่มีไฟล์", + 'mobileTrip.filesNext': "ไฟล์ถัดไป", + 'mobileTrip.filesPrev': "ไฟล์ก่อนหน้า", + 'mobileTrip.googleMaps': "Google แผนที่", + 'mobileTrip.coMaps': "โคแมปส์", + 'mobileTrip.icsDownload': "ดาวน์โหลด .ics", + 'mobileTrip.icsSubscribe': "สมัครสมาชิกปฏิทิน", + 'mobileTrip.icsSubscribeSub': "อัปเดตอัตโนมัติในแอปปฏิทินของคุณ", + 'mobileTrip.importListSub': "วางลิงก์รายการที่แชร์", + 'mobileTrip.importPlaces': "นำเข้าสถานที่", + 'mobileTrip.inCountdown': "ใน {time}", + 'mobileTrip.listView': "มุมมองรายการ", + 'mobileTrip.mapView': "มุมมองแผนที่", + 'mobileTrip.more': "เพิ่มเติม", + 'mobileTrip.newCategory': "หมวดหมู่ใหม่", + 'mobileTrip.newReservation': "การจองใหม่", + 'mobileTrip.notes': "หมายเหตุ", + 'mobileTrip.onMap': "บนแผนที่", + 'mobileTrip.profileDriving': "ขับรถ", + 'mobileTrip.profileWalking': "เดิน", + 'mobileTrip.renameDay': "เปลี่ยนชื่อวัน", + 'mobileTrip.resBadge': "การจอง", + 'mobileTrip.showOnMap': "แสดงบนแผนที่", + 'mobileTrip.statDocuments': "{count} ไฟล์", + 'mobileTrip.statPeople': "{count} คน", + 'mobileTrip.stay': "อยู่", + 'mobileTrip.tapAgainToDelete': "แตะอีกครั้งเพื่อลบ", + 'mobileTrip.todoOpenCount': "เหลือ {count} รายการ", + 'mobileTrip.travel': "การเดินทาง", + 'mobileTrip.upNext': "ต่อไป", + 'mobileTrip.viewDetails': "ดูรายละเอียด", + 'mobileTrip.transportsEmpty': "ยังไม่มีการขนส่ง", + 'mobileTrip.rtInfoTitle': "ข้อมูลการขับรถ", + 'mobileTrip.rtDesktopNote': "กำหนดข้อมูลเหล่านี้บนเดสก์ท็อป ซึ่งคุณยังเปรียบเทียบเส้นทางอื่นและให้วันนั้นตามเส้นทางที่นำเข้าได้", + 'mobileTrip.rtPlanOnDesktop': "การวางแผนทำบนเดสก์ท็อป TREK จะคำนวณการขับรถเมื่อวันหนึ่งมีสถานที่สองแห่ง", + 'mobileTrip.rtSearchOffline': "ต้องเชื่อมต่ออินเทอร์เน็ต: การค้นหาจะอ่านเส้นทางข้างหน้า", + 'mobileTrip.rtBehind': "ช้ากว่าแผน {time}", + 'mobileTrip.rtStart': "เริ่มต้น", + 'mobileTrip.rtStayScope': "เวลาพักเป็นของสถานที่ จึงนับในทุกวันที่วางแผนจุดแวะนี้", + 'mobileTrip.rtStayLess': "น้อยลง {count} นาที", + 'mobileTrip.rtStayMore': "มากขึ้น {count} นาที", + 'mobileTrip.rtNightDesktopOnly': "การจองค้างคืนที่สถานที่นี้ทำได้ในตัววางแผนบนเดสก์ท็อป ที่นี่ทำได้เพียงลบทิ้ง", + 'mobileTrip.rtReach': "ไกลแค่ไหน", + 'mobileTrip.rtReachAhead': "ข้างหน้า {distance}", + 'mobileTrip.rtFromNext': "จากจุดแวะถัดไปของคุณ", + 'mobileTrip.rtFromStart': "จากจุดเริ่มต้นของช่วงเส้นทาง", + 'mobileTrip.rtNoneAhead': "ไม่มีสิ่งใดบนเส้นทางข้างหน้า ลองค้นหาทั้งช่วงเส้นทาง", + 'mobileTrip.rtNoneOnStage': "ไม่มีสิ่งนั้นตลอดช่วงเส้นทางนี้", + 'mobileTrip.rtTruncated.one': "มี 1 ช่วงที่มีผลลัพธ์มากเกินกว่าจะแสดงในคำตอบเดียว เลือกประเภทให้น้อยลงเพื่อดูที่เหลือ", + 'mobileTrip.rtTruncated.other': "มี {count} ช่วงที่มีผลลัพธ์มากเกินกว่าจะแสดงในคำตอบเดียว เลือกประเภทให้น้อยลงเพื่อดูที่เหลือ", +}; +export default mobileTrip; diff --git a/shared/src/i18n/th/mobileVacay.ts b/shared/src/i18n/th/mobileVacay.ts new file mode 100644 index 000000000..50765dae1 --- /dev/null +++ b/shared/src/i18n/th/mobileVacay.ts @@ -0,0 +1,19 @@ +import type { TranslationStrings } from '../types'; + +const mobileVacay: TranslationStrings = { + 'mobileVacay.prevYear': "ปีที่แล้ว", + 'mobileVacay.nextYear': "ปีหน้า", + 'mobileVacay.prevMonth': "เดือนที่แล้ว", + 'mobileVacay.nextMonth': "เดือนหน้า", + 'mobileVacay.usedCount': "{count} ใช้แล้ว", + 'mobileVacay.leftCount': "เหลือ {count} วัน", + 'mobileVacay.left': "คงเหลือ", + 'mobileVacay.modeCompany': "บริษัท", + 'mobileVacay.decreaseAllowance': "ลดจำนวนวันลา", + 'mobileVacay.increaseAllowance': "เพิ่มจำนวนวันลา", + 'mobileVacay.companyLegend': "วันของบริษัท", + 'mobileVacay.editCalendar': "แก้ไขปฏิทิน", + 'mobileVacay.viewYear': "ดูปี", +}; + +export default mobileVacay; diff --git a/shared/src/i18n/th/nav.ts b/shared/src/i18n/th/nav.ts new file mode 100644 index 000000000..2981fcde3 --- /dev/null +++ b/shared/src/i18n/th/nav.ts @@ -0,0 +1,21 @@ +import type { TranslationStrings } from '../types'; + +const nav: TranslationStrings = { + 'nav.trip': "การเดินทาง", + 'nav.share': "แบ่งปัน", + 'nav.settings': "การตั้งค่า", + 'nav.admin': "ผู้ดูแลระบบ", + 'nav.logout': "ออกจากระบบ", + 'nav.lightMode': "โหมดแสง", + 'nav.darkMode': "โหมดมืด", + 'nav.autoMode': "โหมดอัตโนมัติ", + 'nav.administrator': "ผู้ดูแลระบบ", + 'nav.myTrips': "การเดินทางของฉัน", + 'nav.profile': "โปรไฟล์", + 'nav.bottomSettings': "การตั้งค่า", + 'nav.bottomAdmin': "การตั้งค่าผู้ดูแลระบบ", + 'nav.bottomLogout': "ออกจากระบบ", + 'nav.bottomAdminBadge': "ผู้ดูแลระบบ", + 'nav.help': "ช่วยเหลือ", +}; +export default nav; diff --git a/shared/src/i18n/th/notif.ts b/shared/src/i18n/th/notif.ts new file mode 100644 index 000000000..3909e775d --- /dev/null +++ b/shared/src/i18n/th/notif.ts @@ -0,0 +1,50 @@ +import type { TranslationStrings } from '../types'; + +const notif: TranslationStrings = { + 'notif.test.title': "[ทดสอบ] การแจ้งเตือน", + 'notif.test.simple.text': "นี่เป็นการแจ้งเตือนการทดสอบง่ายๆ", + 'notif.test.boolean.text': "คุณยอมรับการแจ้งเตือนการทดสอบนี้หรือไม่", + 'notif.test.navigate.text': "คลิกด้านล่างเพื่อไปยังแดชบอร์ด", + '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': "งานที่ถึงกำหนด", + 'notif.todo_due.text': "{todo} ใน {trip} ครบกำหนดในวันที่ {due}", + 'notif.vacay_invite.title': "คำเชิญรวมปฏิทินวันลา", + 'notif.vacay_invite.text': "{actor} เชิญคุณมารวมแผนวันหยุด", + 'notif.vacay_share.title': "ปฏิทินวันหยุดที่ใช้ร่วมกัน", + 'notif.vacay_share.text': "{actor} แบ่งปันปฏิทินวันหยุดกับคุณ", + 'notif.collection_invite.title': "คำเชิญให้แชร์คอลเลกชัน", + 'notif.collection_invite.text': "{actor} เชิญคุณให้แบ่งปันคอลเล็กชัน", + 'notif.photos_shared.title': "แชร์รูปภาพแล้ว", + 'notif.photos_shared.text': "{actor} แบ่งปันรูปภาพ {count} ใน {trip}", + 'notif.collab_message.title': "ข้อความใหม่", + 'notif.collab_message.text': "{actor} ส่งข้อความใน {trip}", + 'notif.packing_tagged.title': "มอบหมายรายการจัดกระเป๋า", + 'notif.packing_tagged.text': "{actor} มอบหมายให้คุณเป็น {category} ใน {trip}", + 'notif.version_available.title': "มีเวอร์ชันใหม่แล้ว", + 'notif.version_available.text': "TREK {version} มีจำหน่ายแล้ว", + 'notif.replica_failure.title': "การจำลองการจัดเก็บข้อมูลล้มเหลว", + 'notif.replica_failure.text': "การเขียนแบบจำลองล้มเหลวใน '{backend}': {op} จาก {key} — {error}", + 'notif.replica_failure.textSuppressed': "การเขียนแบบจำลองล้มเหลวใน '{backend}': {op} จาก {key} — {error} {suppressed} ความล้มเหลวเพิ่มขึ้นถูกระงับนับตั้งแต่การแจ้งเตือนครั้งล่าสุด", + 'notif.action.view_trip': "ดูการเดินทาง", + 'notif.action.view_collab': "ดูข้อความ", + 'notif.action.view_packing': "ดูการบรรจุ", + 'notif.action.view_photos': "ดูรูปถ่าย", + 'notif.action.view_vacay': "ดูวันหยุดพักผ่อน", + 'notif.action.view_collection': "ดูคอลเลกชัน", + 'notif.action.view_admin': "ไปที่ผู้ดูแลระบบ", + 'notif.action.view': "ดู", + 'notif.action.accept': "ยอมรับ", + 'notif.action.decline': "ปฏิเสธ", + 'notif.plugin.title': "{title}", + 'notif.plugin.text': "{body}", + 'notif.generic.title': "การแจ้งเตือน", + 'notif.generic.text': "คุณมีการแจ้งเตือนใหม่", + 'notif.dev.unknown_event.title': "[DEV] เหตุการณ์ที่ไม่รู้จัก", + 'notif.dev.unknown_event.text': "ประเภทเหตุการณ์ \"{event}\" ไม่ได้ลงทะเบียนใน EVENT_NOTIFICATION_CONFIG", +}; +export default notif; diff --git a/shared/src/i18n/th/notifications.ts b/shared/src/i18n/th/notifications.ts new file mode 100644 index 000000000..3bba8ffc9 --- /dev/null +++ b/shared/src/i18n/th/notifications.ts @@ -0,0 +1,36 @@ +import type { TranslationStrings } from '../types'; + +const notifications: TranslationStrings = { + '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': + "เซิร์ฟเวอร์หรือบัญชีของคุณมีการเปลี่ยนแปลง — ไปที่การตั้งค่าเพื่อทดสอบการเชื่อมต่อของคุณอีกครั้ง", + '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}\"", +}; +export default notifications; diff --git a/shared/src/i18n/th/oauth.ts b/shared/src/i18n/th/oauth.ts new file mode 100644 index 000000000..a8bdd2139 --- /dev/null +++ b/shared/src/i18n/th/oauth.ts @@ -0,0 +1,113 @@ +import type { TranslationStrings } from '../types'; + +const oauth: TranslationStrings = { + 'oauth.scope.group.trips': "ทริป", + 'oauth.scope.group.places': "สถานที่", + 'oauth.scope.group.collections': "คอลเลกชัน", + 'oauth.scope.group.atlas': "แอตลาส", + 'oauth.scope.group.packing': "การบรรจุ", + 'oauth.scope.group.todos': "สิ่งที่ต้องทำ", + '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.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.collections:read.label': "ดูคอลเลกชัน", + 'oauth.scope.collections:read.description': + "อ่านคอลเลกชันสถานที่ที่บันทึกไว้ สถานที่ การให้คะแนน ป้ายกำกับ และสมาชิก", + 'oauth.scope.collections:write.label': "จัดการคอลเลกชัน", + 'oauth.scope.collections: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': "ดูรายการสิ่งที่ต้องทำ", + 'oauth.scope.todos:read.description': "อ่านรายการสิ่งที่ต้องทำในการเดินทางและผู้ได้รับมอบหมายหมวดหมู่", + 'oauth.scope.todos:write.label': "จัดการรายการสิ่งที่ต้องทำ", + 'oauth.scope.todos:write.description': "สร้าง อัปเดต สลับ ลบ และเรียงลำดับรายการสิ่งที่ต้องทำใหม่", + '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': "สร้าง อัปเดต และเพิกถอนลิงก์แชร์สาธารณะสำหรับการเดินทาง", + 'oauth.authorize.authorizing': "กำลังอนุญาต...", + 'oauth.authorize.loading': "กำลังโหลด...", + 'oauth.authorize.errorTitle': "ข้อผิดพลาดในการอนุญาต", + 'oauth.authorize.loginTitle': "ลงชื่อเข้าใช้เพื่อดำเนินการต่อ", + 'oauth.authorize.loginDescription': "{client} ต้องการเข้าถึงบัญชี TREK ของคุณ กรุณาเข้าสู่ระบบก่อน", + 'oauth.authorize.loginButton': "ลงชื่อเข้าใช้ TREK", + 'oauth.authorize.requestLabel': "คำขออนุมัติ", + 'oauth.authorize.requestDescription': "แอปพลิเคชันนี้กำลังขอเข้าถึงบัญชี TREK ของคุณ", + 'oauth.authorize.trustNote': "ให้สิทธิ์การเข้าถึงเฉพาะแอปพลิเคชันที่คุณเชื่อถือเท่านั้น ข้อมูลของคุณอยู่บนเซิร์ฟเวอร์ของคุณ", + 'oauth.authorize.selectScope': "เลือกอย่างน้อยหนึ่งขอบเขต", + 'oauth.authorize.approveOneScope': "อนุมัติ ({count} ขอบเขต)", + 'oauth.authorize.approveManyScopes': "อนุมัติ ({count} ขอบเขต)", + 'oauth.authorize.approveAccess': "อนุมัติการเข้าถึง", + 'oauth.authorize.deny': "ปฏิเสธ", + 'oauth.authorize.choosePermissions': "เลือกสิทธิ์ที่จะให้", + 'oauth.authorize.permissionsRequested': "สิทธิ์ที่ร้องขอ", + 'oauth.authorize.alwaysIncluded': "รวมอยู่เสมอ", + 'oauth.authorize.alwaysTool.listTrips': "แสดงรายการการเดินทางของคุณเพื่อให้ AI สามารถค้นพบรหัสการเดินทางได้", + 'oauth.authorize.alwaysTool.getTripSummary': "อ่านภาพรวมการเดินทางที่จำเป็นเพื่อใช้เครื่องมืออื่นๆ", + 'oauth.scope.group.files': "ไฟล์", + 'oauth.scope.group.settings': "การตั้งค่า", + 'oauth.scope.files:read.label': "ดูไฟล์การเดินทาง", + 'oauth.scope.files:read.description': "แสดงรายการเอกสารในการเดินทาง: ชื่อ ขนาด ผู้อัปโหลด และลิงก์ไปยังไฟล์", + 'oauth.scope.files:write.label': "จัดระเบียบไฟล์การเดินทาง", + 'oauth.scope.files:write.description': "เปลี่ยนชื่อและอธิบายไฟล์ ลิงก์ไปยังการจองและสถานที่ ติดดาวและทิ้งไฟล์เหล่านั้น", + 'oauth.scope.files:content.label': "อ่านเนื้อหาไฟล์", + 'oauth.scope.files:content.description': "อ่านสิ่งที่อยู่ภายในเอกสารที่อัปโหลด เช่น การจอง PDF หรือตั๋ว", + 'oauth.scope.settings:read.label': "ดูการตั้งค่าของคุณ", + 'oauth.scope.settings:read.description': "อ่านหน่วย รูปแบบเวลา ภาษา สกุลเงินเริ่มต้น และหน้าเริ่มต้น", + 'oauth.scope.settings:write.label': "เปลี่ยนการตั้งค่าของคุณ", + 'oauth.scope.settings:write.description': "เปลี่ยนหน่วย รูปแบบเวลา ภาษา สกุลเงินเริ่มต้น และหน้าเริ่มต้น ไม่เคยเก็บคีย์ API", + 'oauth.scope.group.plugins': "ปลั๊กอิน", + 'oauth.scope.plugins:use.label': "เรียกใช้เครื่องมือปลั๊กอิน", + 'oauth.scope.plugins:use.description': "ให้เครื่องมือการเรียกไคลเอ็นต์นี้เผยแพร่โดยปลั๊กอินที่ผู้ดูแลระบบติดตั้งและอนุมัติ ปลั๊กอินแต่ละตัวจะดำเนินการตามสิทธิ์การเข้าถึงที่ได้รับอนุมัติแล้ว ไม่ใช่กับขอบเขตบนโทเค็นนี้", +}; +export default oauth; diff --git a/shared/src/i18n/th/packing.ts b/shared/src/i18n/th/packing.ts new file mode 100644 index 000000000..3c5861bbd --- /dev/null +++ b/shared/src/i18n/th/packing.ts @@ -0,0 +1,213 @@ +import type { TranslationStrings } from '../types'; + +const packing: TranslationStrings = { + 'packing.actions': "การดำเนินการ", + 'packing.editDone': "เสร็จแล้ว", + 'packing.personalEmptyHint': "รายการส่วนตัวของคุณว่างเปล่า — คัดลอกรายการที่ใช้ร่วมกันหรือเพิ่มรายการของคุณเอง", + 'packing.assignMembers': "มอบหมายให้สมาชิก", + 'packing.categoryOptions': "ตัวเลือกรายการ", + 'packing.editItem': "แก้ไขรายการ", + 'packing.itemName': "ชื่อ", + 'packing.itemQuantity': "ปริมาณ", + 'packing.itemWeight': "น้ำหนัก (กรัม)", + 'packing.title': "รายการจัดกระเป๋า", + 'packing.empty': "รายการจัดกระเป๋าว่างเปล่า", + 'packing.import': "นำเข้า", + 'packing.importTitle': "นำเข้ารายการจัดกระเป๋า", + 'packing.importHint': + "หนึ่งรายการต่อบรรทัด รูปแบบ: หมวดหมู่ ชื่อ น้ำหนักเป็นกรัม (ไม่จำเป็น) กระเป๋า (ไม่จำเป็น) เลือก/ไม่เลือก (ไม่จำเป็น)", + 'packing.importPlaceholder': + "สุขอนามัย, แปรงสีฟัน\nเสื้อผ้า เสื้อยืด 200\nเอกสาร, หนังสือเดินทาง, , กระเป๋าถือขึ้นเครื่อง\nเครื่องใช้ไฟฟ้า ที่ชาร์จ 50 กระเป๋าเดินทาง ตรวจเช็คแล้ว", + '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.quantity': "จำนวน", + 'packing.bagName': "ชื่อกระเป๋า...", + 'packing.addBag': "เพิ่มกระเป๋า", + 'packing.changeCategory': "ย้ายไปที่รายการ", + 'packing.makePrivate': "ทำให้เป็นส่วนตัว", + 'packing.makePublic': "ทำให้แชร์ได้", + 'packing.privateHint': "ส่วนตัว — ปรากฏให้คุณเท่านั้น", + 'packing.viewCommon': "แชร์แล้ว", + 'packing.viewPersonal': "รายการของฉัน", + 'packing.share': "การแชร์", + 'packing.tierCommonHint': "อยู่ในรายการส่วนกลางที่ทุกคนมองเห็นได้", + 'packing.tierPersonal': "ส่วนตัว", + 'packing.tierPersonalHint': "ส่วนตัว — มีเพียงคุณเท่านั้นที่สามารถเห็นได้", + 'packing.tierShared': "แชร์กับ...", + 'packing.noOneToShare': "ทริปนี้ยังไม่มีใครเลย", + 'packing.takenCareOf': "โดย {name}", + 'packing.sharedWithCount': "แชร์กับ {count}", + 'packing.broughtBy': "{name} จะนำมา", + 'packing.alsoBring': "ฉันก็สามารถนำสิ่งนั้นมาได้เช่นกัน", + 'packing.alsoBringingStop': "ฉันไม่เอามันมา", + 'packing.cloneToMine': "คัดลอกไปยังรายการของฉัน", + 'packing.confirm.clearChecked': "คุณแน่ใจหรือไม่ว่าต้องการลบรายการที่เลือก {count} ออก", + 'packing.confirm.deleteCat': "คุณแน่ใจหรือไม่ว่าต้องการลบรายการ \"{name}\" ที่มี {count} รายการ", + 'packing.defaultCategory': "อื่นๆ", + 'packing.toast.saveError': "บันทึกไม่สำเร็จ", + 'packing.toast.deleteError': "ลบไม่สำเร็จ", + 'packing.toast.renameError': "เปลี่ยนชื่อไม่สำเร็จ", + 'packing.toast.addError': "เพิ่มไม่สำเร็จ", + 'packing.suggestions.items': [ + { + 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: "เครื่องใช้ในห้องน้ำ", + }, + { + name: "ที่ชาร์จ", + category: "อิเล็กทรอนิกส์", + }, + { + name: "พาวเวอร์แบงค์", + category: "อิเล็กทรอนิกส์", + }, + { + name: "หูฟัง", + category: "อิเล็กทรอนิกส์", + }, + { + name: "อะแดปเตอร์สำหรับการเดินทาง", + category: "อิเล็กทรอนิกส์", + }, + { + name: "กล้อง", + category: "อิเล็กทรอนิกส์", + }, + { + name: "ยาแก้ปวด", + category: "สุขภาพ", + }, + { + name: "พลาสเตอร์ยา", + category: "สุขภาพ", + }, + { + name: "ยาฆ่าเชื้อ", + category: "สุขภาพ", + }, + ], + 'packing.bagLimit': "จำกัดน้ำหนัก", + 'packing.setBagLimit': "กำหนดขีดจำกัด", +}; +export default packing; diff --git a/shared/src/i18n/th/pdf.ts b/shared/src/i18n/th/pdf.ts new file mode 100644 index 000000000..a6e676148 --- /dev/null +++ b/shared/src/i18n/th/pdf.ts @@ -0,0 +1,14 @@ +import type { TranslationStrings } from '../types'; + +const pdf: TranslationStrings = { + 'pdf.travelPlan': "แผนการเดินทาง", + 'pdf.planned': "วางแผนแล้ว", + 'pdf.costLabel': "ราคา", + 'pdf.preview': "ดูตัวอย่าง PDF", + 'pdf.saveAsPdf': "บันทึกเป็น PDF", + 'pdf.pageBreakPerDay': "ขึ้นหน้าใหม่ทุกวัน", + 'pdf.mapTitle': "ภาพรวมเส้นทาง", + 'pdf.distanceLabel': "ระยะทาง", + 'pdf.mapCredit': "ขอบเขตประเทศ: geoBoundaries (CC BY 4.0)", +}; +export default pdf; diff --git a/shared/src/i18n/th/perm.ts b/shared/src/i18n/th/perm.ts new file mode 100644 index 000000000..dfb7e4b22 --- /dev/null +++ b/shared/src/i18n/th/perm.ts @@ -0,0 +1,51 @@ +import type { TranslationStrings } from '../types'; + +const perm: TranslationStrings = { + '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': "ใครสามารถสร้างหรือลบลิงก์แชร์สาธารณะได้", +}; +export default perm; diff --git a/shared/src/i18n/th/photos.ts b/shared/src/i18n/th/photos.ts new file mode 100644 index 000000000..4bf569ee1 --- /dev/null +++ b/shared/src/i18n/th/photos.ts @@ -0,0 +1,25 @@ +import type { TranslationStrings } from '../types'; + +const photos: TranslationStrings = { + 'photos.title': "ภาพถ่าย", + 'photos.subtitle': "{count} รูปภาพสำหรับ {trip}", + '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 รูปภาพ", +}; +export default photos; diff --git a/shared/src/i18n/th/places.ts b/shared/src/i18n/th/places.ts new file mode 100644 index 000000000..1c6aac9b7 --- /dev/null +++ b/shared/src/i18n/th/places.ts @@ -0,0 +1,136 @@ +import type { TranslationStrings } from '../types'; + +const places: TranslationStrings = { + 'places.addPlace': "เพิ่มสถานที่/กิจกรรม", + 'places.importFile': "นำเข้าไฟล์", + 'places.trackIndicator': "เส้นทางที่บันทึกไว้", + 'places.sidebarDrop': "วางเพื่อนำเข้า", + 'places.importFileHint': + "นำเข้าไฟล์ .gpx, .kml หรือ .kmz จากเครื่องมือ เช่น Google My Maps, Google Earth หรือเครื่องติดตาม GPS", + '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': "เลือกอย่างน้อยหนึ่งประเภทที่จะนำเข้า", + 'places.kmlImportTypes': "คุณต้องการนำเข้าอะไร?", + 'places.kmlImportPoints': "จุด (หมุด)", + 'places.kmlImportPaths': "เส้นทาง (LineStrings)", + 'places.kmlImportNoneSelected': "เลือกอย่างน้อยหนึ่งประเภทที่จะนำเข้า", + 'places.selectionCount': "เลือกแล้ว {count} รายการ", + 'places.deleteSelected': "ลบที่เลือกไว้", + 'places.changeCategory': "เปลี่ยนหมวดหมู่", + 'places.categoryChanged': "เปลี่ยนหมวดหมู่สถานที่แล้ว {count} แห่ง", + 'places.kmlKmzImported': "{count} สถานที่นำเข้าจาก KMZ/KML", + 'places.urlResolved': "สถานที่ที่นำเข้าจาก URL", + 'places.importList': "รายการนำเข้า", + 'places.kmlKmzSummaryValues': "หมุด: {total} • นำเข้า: {created} • ข้าม: {skipped}", + 'places.importGoogleList': "รายการ Google", + 'places.importNaverList': "เนเวอร์ลิสต์", + 'places.googleListHint': "วางลิงก์รายการ Google Maps ที่แชร์เพื่อนำเข้าสถานที่ทั้งหมด", + 'places.googleListImported': "{count} สถานที่นำเข้าจาก \"{list}\"", + 'places.googleListError': "ไม่สามารถนำเข้ารายการ Google Maps", + 'places.naverListHint': "วางลิงก์รายการ Naver Maps ที่แชร์เพื่อนำเข้าสถานที่ทั้งหมด", + 'places.naverListImported': "{count} สถานที่นำเข้าจาก \"{list}\"", + 'places.naverListError': "ไม่สามารถนำเข้ารายการ Naver Maps", + 'places.viewDetails': "ดูรายละเอียด", + 'places.assignToDay': "เพิ่มในวันใด?", + 'places.all': "ทั้งหมด", + 'places.unplanned': "ไม่ได้วางแผน", + 'places.planned': "วางแผนแล้ว", + 'places.filterTracks': "แทร็ก", + 'places.filterByRating': "กรองตามคะแนน", + 'places.yourRating': "คะแนนของคุณ", + 'places.notRated': "ยังไม่ได้รับการจัดอันดับ", + '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.newCategory': "หมวดหมู่ใหม่", + 'places.categoryNamePlaceholder': "ชื่อหมวดหมู่", + 'places.formTime': "เวลา", + 'places.startTime': "เริ่ม", + 'places.endTime': "สิ้นสุด", + 'places.endTimeBeforeStart': "เวลาสิ้นสุดอยู่ก่อนเวลาเริ่มต้น", + 'places.timeCollision': "เวลาที่ทับซ้อนกันกับ:", + 'places.formWebsite': "เว็บไซต์", + 'places.formNotes': "หมายเหตุ", + 'places.formNotesPlaceholder': "บันทึกส่วนตัว...", + 'places.assignmentNotes': "หมายเหตุสำหรับวันนี้", + 'places.assignmentNotesPlaceholder': "หมายเหตุสำหรับสถานที่นี้เฉพาะวันนี้เท่านั้น...", + 'places.formReservation': "การจอง", + 'places.reservationNotesPlaceholder': "บันทึกการจอง เลขที่ยืนยัน...", + 'places.mapsSearchPlaceholder': "ค้นหาสถานที่...", + 'places.mapsSearchError': "การค้นหาสถานที่ล้มเหลว", + 'places.loadingDetails': "กำลังโหลดรายละเอียดสถานที่...", + 'places.osmHint': + "ใช้การค้นหา OpenStreetMap (ไม่มีรูปภาพ เวลาทำการ หรือการให้คะแนน) เพิ่มคีย์ Google API ในการตั้งค่าเพื่อดูรายละเอียดทั้งหมด", + 'places.details.title': "รายละเอียดสถานที่", + 'places.details.empty': "เลือกผลการค้นหาเพื่อดูรูปภาพและคำอธิบาย", + 'places.details.loading': "กำลังโหลดรายละเอียด...", + 'places.details.error': "ไม่สามารถโหลดรายละเอียดได้", + 'places.details.disabled': "การเพิ่มข้อมูลถูกปิดโดยผู้ดูแลระบบ", + 'places.details.noPhotos': "ไม่พบรูปภาพสำหรับสถานที่นี้", + 'places.details.pickImage': "เลือกรูปภาพ", + 'places.details.description': "คำอธิบาย", + 'places.details.adopt': "ใช้ข้อความนี้", + 'places.details.adoptBlocked': "ล้างช่องคำอธิบายก่อน", + 'places.details.facts': "ข้อมูลน่ารู้", + 'places.details.nothing': "ไม่พบสิ่งใดสำหรับสถานที่นี้", + 'places.details.aboutBrand': "เกี่ยวกับแบรนด์", + 'places.details.aboutBrandNote': "ข้อมูลนี้อธิบายแบรนด์ ไม่ใช่สาขานี้", + 'places.details.fact.rating': "เรตติ้ง", + 'places.details.fact.cuisine': "อาหาร", + 'places.details.fact.openingHours': "เวลาทำการ", + 'places.details.fact.menu': "เมนู", + 'places.details.fact.outdoorSeating': "ที่นั่งกลางแจ้ง", + 'places.details.fact.takeaway': "ซื้อกลับบ้าน", + 'places.details.fact.delivery': "จัดส่ง", + 'places.details.fact.wheelchair': "การเข้าถึงแบบไม่มีขั้นตอน", + 'places.details.fact.vegetarian': "มังสวิรัติ", + 'places.details.fact.vegan': "วีแกน", + 'places.details.fact.internetAccess': "อินเตอร์เน็ตไร้สาย", + 'places.categoryCreateError': "ไม่สามารถสร้างหมวดหมู่ได้", + 'places.nameRequired': "กรุณากรอกชื่อ", + 'places.saveError': "บันทึกไม่สำเร็จ", + 'places.createExpenseHint': "บันทึกสถานที่ จากนั้นเปิดตัวแก้ไขต้นทุน", + 'places.duplicateExists': "'{name}' อยู่ในทริปนี้แล้ว", + 'places.addAnyway': "เพิ่มต่อไป", + 'places.enrichOnImport': "เติมเต็มสถานที่ผ่าน Google", + 'places.enrichOnImportHint': + "ค้นหาสถานที่ที่นำเข้าแต่ละแห่งเพื่อกรอกรูปภาพ ที่อยู่ และรายละเอียดการติดต่อ ใช้คีย์ Google Maps ของคุณ", + 'places.uploadImage': "อัปโหลดรูปภาพ", + 'places.changeImage': "เปลี่ยนภาพ", + 'places.removeImage': "ลบรูปภาพ", + 'places.imageUploadError': "ไม่สามารถอัปโหลดภาพได้", + 'places.imageRemoveError': "ไม่สามารถลบรูปภาพได้", + 'places.addToSelectedDay': "เพิ่มในวันที่เปิดอยู่", + 'places.addPlaceShort': "สถานที่ใหม่", + 'places.addToDayShort': "เพิ่มในวัน", + 'places.googleDirHint': "ใช้ลิงก์เส้นทางได้เช่นกัน: จุดแวะจะกลายเป็นสถานที่ตามลำดับการขับรถ", + 'places.dayScoped': "แสดงเฉพาะวันที่เปิดอยู่", + 'places.dayScopedClear': "แสดงทั้งทริป", + 'places.source.amap': "Amap", +}; +export default places; diff --git a/shared/src/i18n/th/planner.ts b/shared/src/i18n/th/planner.ts new file mode 100644 index 000000000..eceb16924 --- /dev/null +++ b/shared/src/i18n/th/planner.ts @@ -0,0 +1,67 @@ +import type { TranslationStrings } from '../types'; + +const planner: TranslationStrings = { + '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': "เช่น S3 เวลา 14:30 น. จากสถานีกลาง เรือเฟอร์รี่จากท่าเรือ 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 Maps", + 'planner.openCoMaps': "เปิดใน CoMaps", + '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}", +}; +export default planner; diff --git a/shared/src/i18n/th/register.ts b/shared/src/i18n/th/register.ts new file mode 100644 index 000000000..43debd56e --- /dev/null +++ b/shared/src/i18n/th/register.ts @@ -0,0 +1,25 @@ +import type { TranslationStrings } from '../types'; + +const register: TranslationStrings = { + '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': "เข้าสู่ระบบ", +}; +export default register; diff --git a/shared/src/i18n/th/reservations.ts b/shared/src/i18n/th/reservations.ts new file mode 100644 index 000000000..b35cd181c --- /dev/null +++ b/shared/src/i18n/th/reservations.ts @@ -0,0 +1,181 @@ +import type { TranslationStrings } from '../types'; + +const reservations: TranslationStrings = { + '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.urlLabel': "ลิงก์", + 'reservations.urlPlaceholder': "https://...", + 'reservations.meta.airline': "สายการบิน", + 'reservations.meta.flightNumber': "หมายเลขเที่ยวบิน", + 'reservations.meta.from': "จาก", + 'reservations.meta.to': "ถึง", + 'reservations.layover.route': "เส้นทาง", + 'reservations.layover.stop': "จุดแวะพัก", + 'reservations.layover.addStop': "เพิ่มจุดแวะ", + 'reservations.layover.connection': "การเชื่อมต่อ", + 'reservations.layover.layover': "แวะพัก", + 'reservations.needsReview': "ตรวจสอบ", + 'reservations.needsReviewHint': "ไม่สามารถจับคู่สนามบินได้โดยอัตโนมัติ — โปรดยืนยันตำแหน่ง", + 'reservations.searchLocation': "ค้นหาสถานี ท่าเรือ หรือที่อยู่…", + 'reservations.meta.trainNumber': "หมายเลขรถไฟ", + 'reservations.meta.platform': "แพลตฟอร์ม", + 'reservations.meta.seat': "ที่นั่ง", + 'reservations.meta.checkIn': "เช็คอิน", + 'reservations.meta.checkInUntil': "เช็คอินจนถึง", + 'reservations.meta.checkOut': "เช็คเอาท์", + 'reservations.meta.linkAccommodation': "ที่พัก", + 'reservations.meta.pickAccommodation': "ลิงก์ที่พัก", + 'reservations.meta.noAccommodation': "ไม่มี", + 'reservations.meta.hotelPlace': "ที่พัก", + 'reservations.meta.linkPlace': "สถานที่/กิจกรรม", + 'reservations.meta.pickPlace': "เลือกสถานที่/กิจกรรม", + '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.parking': "ที่จอดรถ", + 'reservations.type.other': "อื่นๆ", + 'reservations.type.bus': "รถบัส", + 'reservations.type.ferry': "เรือเฟอร์รี่", + 'reservations.type.bicycle': "จักรยาน", + 'reservations.type.taxi': "แท็กซี่", + 'reservations.type.transit': "การขนส่งสาธารณะ", + 'reservations.type.transport_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, โรงแรมแอดลอน, ...", + 'reservations.locationAddress': "ที่ตั้ง / ที่อยู่", + 'reservations.locationPlaceholder': "ที่อยู่ สนามบิน โรงแรม...", + 'reservations.confirmationCode': "รหัสการจอง", + 'reservations.confirmationPlaceholder': "เช่น เอบีซี12345", + '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': "เขตเวลาออกเดินทาง", + 'reservations.meta.arrivalTimezone': "เขตเวลาถึง", + 'reservations.span.departure': "ออกเดินทาง", + 'reservations.span.arrival': "มาถึง", + 'reservations.span.inTransit': "ระหว่างทาง", + // span.pickup does double duty: the day a rental car is picked up, and the day a + // multi-day parking ends and you collect your own car again. Both read the same way + // in every locale, so parking only needs the drop-off wording of its own. + 'reservations.span.pickup': "รับรถ", + 'reservations.span.dropOff': "นำรถไปจอด/คืนรถ", + 'reservations.span.return': "กลับ", + 'reservations.span.active': "ใช้งานอยู่", + 'reservations.span.start': "เริ่ม", + 'reservations.span.end': "สิ้นสุด", + 'reservations.span.ongoing': "กำลังดำเนินการอยู่", + 'reservations.validation.endBeforeStart': "วันที่/เวลาสิ้นสุดต้องอยู่หลังวันที่/เวลาเริ่มต้น", + 'reservations.addBooking': "เพิ่มการจอง", + 'reservations.import.title': "นำเข้าการยืนยันการจอง", + 'reservations.import.cta': "นำเข้าจากไฟล์", + 'reservations.import.dropHere': "วางไฟล์ยืนยันการจองที่นี่ หรือคลิกเพื่อเลือก", + 'reservations.import.dropActive': "วางไฟล์ที่จะนำเข้า", + 'reservations.import.acceptedFormats': "ยอมรับ: EML, PDF, PKPass, HTML, TXT (สูงสุด 10 MB ต่อไฟล์ สูงสุด 5 ไฟล์)", + 'reservations.import.parsing': "กำลังแยกวิเคราะห์ไฟล์...", + 'reservations.import.previewHeading': "พบการจอง {count} แล้ว", + 'reservations.import.previewEmpty': "ไม่สามารถแยกการจองออกจากไฟล์ที่อัปโหลดได้", + 'reservations.import.removeItem': "ลบ", + 'reservations.import.needsReview': "ตรวจสอบ", + 'reservations.import.tryAi': "ลองแยกวิเคราะห์ AI", + 'reservations.import.aiParsing': "แยกวิเคราะห์ด้วย AI...", + 'reservations.import.confirm': "นำเข้าการจอง {count}", + 'reservations.import.back': "กลับ", + 'reservations.import.success': "{count} นำเข้าการจองแล้ว", + 'reservations.import.partialFailure': "นำเข้าสำเร็จ {created} รายการ ล้มเหลว {failed} รายการ", + 'reservations.import.error': "การแยกวิเคราะห์ล้มเหลว ตรวจสอบให้แน่ใจว่าไฟล์นั้นเป็นข้อมูลยืนยันการจองที่ถูกต้อง", + 'reservations.import.unavailable': "การนำเข้าการจองไม่พร้อมใช้งานบนเซิร์ฟเวอร์นี้", + 'reservations.import.unsupportedFormat': "รูปแบบไฟล์ที่ไม่รองรับ ใช้ EML, PDF, PKPass, HTML หรือ TXT", + 'reservations.import.fileTooLarge': "ไฟล์ \"{name}\" เกินขีดจำกัด 10 MB", + 'reservations.airtrail.title': "นำเข้าจาก AirTrail", + 'reservations.airtrail.cta': "แอร์เทรล", + 'reservations.airtrail.synced': "แอร์เทรล", + 'reservations.airtrail.syncedHint': "ซิงค์จาก AirTrail - การแก้ไขจะซิงค์กันทั้งสองทาง", + 'reservations.airtrail.notSynced': "ไม่ได้ซิงค์", + 'reservations.airtrail.notSyncedHint': "เที่ยวบินนี้ถูกลบใน AirTrail และไม่มีการซิงค์อีกต่อไป", + 'reservations.airtrail.layoverHint': + "นำเข้าจากแอร์เทรล เที่ยวบินหลายขาที่มีการต่อเครื่องจะไม่มีเที่ยวบิน AirTrail เดียวที่จะซิงค์กลับไป ดังนั้นจึงถือเป็นการนำเข้าครั้งเดียว", + 'reservations.airtrail.loadError': "ไม่สามารถโหลดเที่ยวบิน AirTrail ของคุณได้", + 'reservations.airtrail.imported': "นำเข้าเที่ยวบินแล้ว {count} เที่ยวบิน", + 'reservations.airtrail.skippedDuplicate': "มีอยู่ในทริปนี้แล้ว {count} เที่ยวบิน ข้ามรายการ", + 'reservations.airtrail.nothingImported': "ไม่มีอะไรจะนำเข้า", + 'reservations.airtrail.importError': "การนำเข้าล้มเหลว โปรดลองอีกครั้ง", + 'reservations.airtrail.undo': "นำเข้าจาก AirTrail", + 'reservations.airtrail.alreadyImported': "นำเข้า", + 'reservations.airtrail.duringTrip': "ในระหว่างการเดินทางครั้งนี้", + 'reservations.airtrail.otherFlights': "เที่ยวบินอื่นๆ", + 'reservations.airtrail.empty': "ไม่พบเที่ยวบินในบัญชี AirTrail ของคุณ", + 'reservations.airtrail.importCta': "นำเข้า {count}", + 'reservations.airtrail.joinConnection': "นำเข้าเป็นเที่ยวบินเดียวโดยมีการแวะพักใน {stops}", + 'reservations.costsLabel': "ค่าใช้จ่าย", + 'reservations.createExpense': "สร้างรายจ่าย", + 'reservations.createExpenseHint': "บันทึกการจอง จากนั้นเปิดตัวแก้ไขต้นทุน", + 'reservations.linkedExpense': "ค่าใช้จ่ายที่เชื่อมโยง", + 'reservations.removeExpense': "ลบค่าใช้จ่าย", + 'reservations.travelers.label': "นักเดินทาง", + 'reservations.travelers.assign': "มอบหมายให้นักเดินทาง", + 'reservations.travelers.none': "ยังไม่มีสมาชิกทริป", +}; +export default reservations; diff --git a/shared/src/i18n/th/roadtrip.ts b/shared/src/i18n/th/roadtrip.ts new file mode 100644 index 000000000..39b545b19 --- /dev/null +++ b/shared/src/i18n/th/roadtrip.ts @@ -0,0 +1,249 @@ +import type { TranslationStrings } from '../types'; + +const roadtrip: TranslationStrings = { + 'roadtrip.stay.portals': "ค้นหาที่พัก", + 'roadtrip.stay.portalHint': "ตรวจสอบปลายทาง วันที่ และผู้เข้าพักในพอร์ทัล CHECK24 ต้องค้นหาด้วยตนเอง", + 'roadtrip.charging.available': "พร้อมใช้งาน", + 'roadtrip.charging.unknown': "ไม่มีข้อมูลที่เชื่อถือได้", + 'roadtrip.charging.stale': "สถานะล้าสมัย", + 'roadtrip.charging.prices': "อัตราค่าบริการที่เผยแพร่", + 'roadtrip.charging.note': "เป็นอัตราที่เผยแพร่ ภาษี เงื่อนไข และค่าธรรมเนียมเพิ่มเติมอาจมีผล ราคาในบัตรชาร์จของคุณอาจต่างกัน", + 'roadtrip.charging.coverage': "ข้อมูลเปิด ความครอบคลุมต่างกันตามภูมิภาคและผู้ให้บริการ", + 'roadtrip.charging.availability': "ความพร้อมใช้งานและราคา", + 'roadtrip.import.title': "นำเข้าเส้นทาง Google Maps", + 'roadtrip.import.note': "จุดแวะจะถูกเพิ่มต่อท้ายวันที่เลือก TREK จะคำนวณเส้นทางใหม่", + 'roadtrip.import.unresolved': "ไม่พบตำแหน่ง ข้ามจุดแวะนี้", + 'roadtrip.import.day': "วัน", + 'roadtrip.hazards.show': "แสดงพื้นที่อันตราย", + 'roadtrip.hazards.current': "คำเตือนปัจจุบัน", + 'roadtrip.hazards.note': "คำเตือนไม่ได้หมายถึงการปิดถนน เส้นทางจะไม่เปลี่ยน", + 'roadtrip.hazards.point': "มีเพียงตำแหน่ง ไม่ทราบพื้นที่ที่ได้รับผลกระทบ", + 'roadtrip.hazards.loading': "กำลังโหลดคำเตือน…", + 'roadtrip.hazards.unavailable': "ไม่พร้อมใช้งาน", + 'roadtrip.hazards.offline': "ออฟไลน์: ไม่มีคำเตือนแบบเรียลไทม์", + 'roadtrip.hazards.partial': "ความครอบคลุมจำกัด", + 'roadtrip.stops.section': "จุดแวะบริการ", + 'roadtrip.stops.inDays': "แสดงในหน้าวันด้วย", + 'roadtrip.stops.daysHint': "เมื่อปิด จุดแวะบริการทั้งหมดจะแสดงเฉพาะใน Roadtrip", + 'roadtrip.window.dragHint': "ขณะออนไลน์ ลากจุดสิ้นสุดวันไปตามเส้นทางหรือไปยังสถานที่ คลิกขวาเพื่อคืนจุดสิ้นสุดอัตโนมัติ", + 'roadtrip.window.resetBoundaries': "คืนจุดสิ้นสุดวันอัตโนมัติ", + 'roadtrip.window.endHere': "สิ้นสุดวันที่นี่", + 'roadtrip.window.endHereHint': "คุณสามารถสิ้นสุดวันที่จุดแวะที่กำหนดได้จากรายละเอียดสถานที่ เมื่อเปิดโหมด Roadtrip และกำหนดเวลาเดินทางรายวัน", + 'roadtrip.window.endAt': "สิ้นสุดวัน", + 'roadtrip.window.onRoute': "ตามเส้นทาง", + 'roadtrip.window.atStop': "ที่สถานที่สุดท้าย", + 'roadtrip.window.routeHint': "พักตามเส้นทางเมื่อถึงเวลาสิ้นสุด", + 'roadtrip.window.stopHint': "หยุดก่อนที่สถานที่ถัดไปจะทำให้เกินเวลาสิ้นสุด", + 'roadtrip.window.legTooLong': "ช่วงขับรถยาวเกินกรอบเวลาเดินทางรายวัน เพิ่มสถานที่ระหว่างทางหรือเลือกพักตามเส้นทาง", + 'roadtrip.window.pointLabel': "สิ้นสุดวันที่ {day} เวลา {time}", + 'roadtrip.window.title': "เวลาเดินทางรายวัน", + 'roadtrip.window.start': "เวลาเริ่มต้นวัน", + 'roadtrip.window.end': "เวลาสิ้นสุดวัน", + 'roadtrip.window.hint': "กำหนดทั้งสองเวลาเพื่อเปิดใช้ เวลาที่กำหนดเองมีความสำคัญกว่า", + 'roadtrip.window.invalid': "เวลาสิ้นสุดต้องหลังเวลาเริ่มต้น", + 'roadtrip.window.stop': "สิ้นสุดวัน", + 'roadtrip.window.resume': "เดินทางต่อ", + 'roadtrip.window.pointHint': "นี่คือจุดพักค้างคืนโดยประมาณของคุณ", + 'roadtrip.window.departure': "เดินทางต่อหลังจากแวะที่เหลือ เวลา {time}", + 'roadtrip.window.showPoint': "แสดงบนแผนที่", + 'roadtrip.window.incomplete': "ยังคำนวณช่วงพักรายวันไม่ได้จนกว่าจะมีเส้นทางเชื่อมต่อครบ", + 'roadtrip.window.conflict': "เวลาที่กำหนดขัดกับการขับรถและช่วงพักรายวัน เวลาที่กำหนดเองจะไม่เปลี่ยน แต่การจัดตารางอัตโนมัติถูกพักไว้", + 'roadtrip.window.tooLong': "เวลาเดินทางนี้ต้องใช้วันเพิ่มมากกว่า 365 วัน เลือกกรอบเวลารายวันที่นานขึ้น", + 'roadtrip.mode.roadtrip': "โรดทริป", + 'roadtrip.mode.days': "วัน", + 'roadtrip.mode.label': "มุมมองแผน", + 'roadtrip.title': "โรดทริป", + 'roadtrip.subtitle': "จุดแวะ เวลาเดินทาง และเวลาถึงสำหรับทริปนี้", + 'roadtrip.empty.title': "ยังไม่มีเส้นทาง", + 'roadtrip.stops.label': "จุดแวะระหว่างทาง", + 'roadtrip.stops.remove': "ลบจุดแวะ", + 'roadtrip.poi.title': "ตามเส้นทาง", + 'roadtrip.poi.scope': "วัน", + 'roadtrip.poi.looking': "กำลังมองหา", + 'roadtrip.poi.searchingHint': "กำลังค้นหาตามเส้นทาง…", + 'roadtrip.poi.found': "พบ {count} แห่งระหว่างทาง", + 'roadtrip.poi.fuel': "เชื้อเพลิง", + 'roadtrip.poi.charging': "จุดชาร์จ", + 'roadtrip.stop.offRoad': "ห่างจากถนน {distance}", + 'roadtrip.via.plugin': "จุดแวะระหว่างทาง", + 'roadtrip.limit.title': "การตั้งค่าการขับรถ", + 'roadtrip.limit.legLabel': "ขับรถต่อเนื่องได้นานที่สุด", + 'roadtrip.limit.dayLabel': "เวลาขับรถต่อวัน", + 'roadtrip.limit.rangeLabel': "ระยะทางต่อหนึ่งถัง", + 'roadtrip.limit.fillLabel': "เติมถึง", + 'roadtrip.limit.fillFull': "เต็ม", + 'roadtrip.limit.fillBadge': "เติมถึง {percent} %", + 'roadtrip.limit.wearNote': "สูญเสียจากอายุ {percent} %", + 'roadtrip.limit.rangeLabelCharge': "ระยะทางต่อการชาร์จหนึ่งครั้ง", + 'roadtrip.limit.sectionTrip': "ทริปนี้", + 'roadtrip.limit.sectionDriving': "การขับรถ", + 'roadtrip.limit.sectionVehicle': "ยานพาหนะ", + 'roadtrip.limit.tankLabel': "ขนาดถัง", + 'roadtrip.limit.batteryLabel': "แบตเตอรี่", + 'roadtrip.limit.useLabel': "อัตราสิ้นเปลือง", + 'roadtrip.limit.wearLabel': "การเสื่อมของแบตเตอรี่", + 'roadtrip.limit.computed': "คำนวณจากข้อมูลรถ", + 'roadtrip.limit.perFill': "ต่อถัง", + 'roadtrip.limit.perCharge': "ต่อการชาร์จ", + 'roadtrip.limit.afterFill': "การแวะเติม {percent} % ทำให้ไปได้ {distance}", + 'roadtrip.limit.fullNote': "จุดแวะนี้เติมเต็มถัง", + 'roadtrip.limit.rangeEmpty': "ยังไม่ได้กำหนดระยะทาง", + 'roadtrip.limit.rangeEmptyHint': "กรอกระยะทาง หรือกรอกข้อมูลด้านล่างเพื่อให้ TREK คำนวณ", + 'roadtrip.limit.specHint': "รายละเอียดรถกำหนดระยะทาง", + 'roadtrip.limit.vehicleHint': "เลือกรถเพื่อคำนวณระยะทาง", + 'roadtrip.limit.minutes': "นาที", + 'roadtrip.limit.off': "ปิด", + 'roadtrip.limit.blockNote': "หนึ่งช่วง = {distance}", + 'roadtrip.limit.echoOver': "เกินขีดจำกัด {over} จาก {days} วัน", + 'roadtrip.limit.echoNone': "ทั้ง {days} วันอยู่ในขีดจำกัด", + 'roadtrip.limit.echoDry': "มี {count} ช่วงที่ไม่มีจุดแวะที่ไปถึงได้", + 'roadtrip.limit.echoEmpty': "เปิดโรดทริปเพื่อดูผลของการตั้งค่าเหล่านี้", + 'roadtrip.limit.specToggle': "คำนวณจากข้อมูลรถ", + 'roadtrip.limit.hint': "เฉพาะเวลาขับรถ ไม่รวมการพักและช่วงค้างคืน", + 'roadtrip.limit.legOver': "เกินเวลาขับรถต่อเนื่องสูงสุด {time}", + 'roadtrip.limit.dayOver': "เกิน {time}", + 'roadtrip.limit.range': "{distance} ตั้งแต่เติมครั้งล่าสุด", + 'roadtrip.limit.none': "ไม่ได้กำหนด", + 'roadtrip.line.section': "เส้นทาง", + 'roadtrip.line.connect': "เชื่อมต่อวัน", + 'roadtrip.line.dayColors': "สีแยกตามวัน", + 'roadtrip.line.hint': "การขับรถเชื่อมต่อจะนับรวมในวันที่เดินทางถึง", + 'roadtrip.avoid.section': "หลีกเลี่ยงเมื่อทำได้", + 'roadtrip.avoid.toll': "ถนนเก็บค่าผ่านทาง", + 'roadtrip.avoid.motorway': "ทางด่วน", + 'roadtrip.avoid.ferry': "เรือเฟอร์รี่", + 'roadtrip.avoid.hint': "หลีกเลี่ยงเมื่อทำได้ ข้อยกเว้นจะแสดงให้ทราบ", + 'roadtrip.avoid.unavailable': "ผู้ให้บริการเส้นทางของคุณไม่รองรับการหลีกเลี่ยง", + 'roadtrip.avoid.badge': "หลีกเลี่ยงแล้ว {count}", + 'roadtrip.avoid.missed': "หลีกเลี่ยง {classes} ไม่ได้", + 'roadtrip.avoid.missedHint': "วันนี้ไม่มีเส้นทางอ้อม จึงต้องใช้เส้นทางนี้ วันอื่นยังคงหลีกเลี่ยงเท่าที่ทำได้", + 'roadtrip.refuel.dry': "น้ำมันหมดที่นี่", + 'roadtrip.refuel.after': "หลังจาก {distance}", + 'roadtrip.limit.vehicleLabel': "ประเภทรถ", + 'roadtrip.limit.vehicleAny': "ได้ทั้งสองแบบ", + 'roadtrip.limit.vehicleCombustion': "รถน้ำมัน", + 'roadtrip.limit.vehicleElectric': "รถไฟฟ้า", + 'roadtrip.refuel.dryElectric': "แบตเตอรี่หมดที่นี่", + 'roadtrip.refuel.findElectric': "หาจุดชาร์จ", + 'roadtrip.refuel.find': "หาปั๊มน้ำมัน", + 'roadtrip.refuel.again': "ลองอีกครั้ง", + 'roadtrip.refuel.looking': "กำลังค้นหาตามเส้นทาง…", + 'roadtrip.refuel.spare': "เหลือระยะทาง {distance}", + 'roadtrip.refuel.add': "เพิ่ม {name} เป็นจุดเติมน้ำมัน", + 'roadtrip.refuel.addElectric': "เพิ่ม {name} เป็นจุดชาร์จ", + 'roadtrip.refuel.none': "ไม่พบสิ่งใดในช่วงที่ไปถึงได้", + 'roadtrip.refuel.incomplete': "การค้นหาหยุดก่อนจบ จึงตรวจสอบช่วงนี้ไม่ครบ", + 'roadtrip.refuel.failed': "การค้นหาสถานที่ไม่ตอบกลับ", + 'roadtrip.stop.none': "จุดหมาย", + 'roadtrip.stay.mode.pause': "พัก", + 'roadtrip.stay.mode.night': "ค้างคืน", + 'roadtrip.stay.nightAdded': "เพิ่มเป็นที่พักค้างคืนแล้ว", + 'roadtrip.stay.nightAction': "เพิ่มเป็นที่พักค้างคืน", + 'roadtrip.stop.makeService': "กำหนดเป็นจุดแวะระหว่างทาง", + 'roadtrip.stop.changeKind': "เปลี่ยนประเภทจุดแวะ", + 'roadtrip.stop.backToDestination': "กลับเป็นจุดหมาย", + 'roadtrip.poi.anySocket': "หัวชาร์จทุกแบบ", + 'roadtrip.poi.anyPower': "กำลังไฟทุกระดับ", + 'roadtrip.poi.free': "ฟรี", + 'roadtrip.poi.wholeDay': "ตลอดวัน", + 'roadtrip.poi.midLeg': "กึ่งกลางระหว่าง {from} ถึง {to}", + 'roadtrip.track.title': "วันที่ {number} ใช้แทร็ก", + 'roadtrip.track.hint': "ให้วันนี้เดินทางตามแทร็กที่นำเข้า", + 'roadtrip.track.badge': "แทร็ก", + 'roadtrip.track.untitled': "แทร็กไม่มีชื่อ", + 'roadtrip.track.empty': "ไม่มีแทร็กในทริปนี้", + 'roadtrip.track.emptyHint': "นำเข้าไฟล์ GPX หรือ KML แล้วแทร็กจะแสดงที่นี่", + 'roadtrip.track.length': "ยาว {distance}", + 'roadtrip.track.gap': "ห่างจากวันนี้ {distance}", + 'roadtrip.track.onDay': "ตลอดวันนี้", + 'roadtrip.track.explain': "การขับรถจะถูกดึงให้ตามแทร็กด้วยจุดผ่านทางหลายจุด จุดผ่านทางเดิมในช่วงเหล่านั้นจะถูกแทนที่", + 'roadtrip.track.action': "เดินทางตามแทร็กนี้", + 'roadtrip.track.working': "กำลังปรับเส้นทางให้เข้ากับแทร็ก รอบที่ {round}", + 'roadtrip.track.done': "วางจุดผ่านทาง {count} จุดแล้ว เส้นทางอยู่ห่างจากแทร็กไม่เกิน {distance}", + 'roadtrip.track.capped': "วางจุดผ่านทาง {count} จุดแล้ว จุดที่ห่างที่สุดยังห่างจากแทร็ก {distance}", + 'roadtrip.track.already': "เส้นทางนี้ตามแทร็กนี้อยู่แล้ว", + 'roadtrip.track.errorRoute': "บริการคำนวณเส้นทางไม่ตอบกลับ", + 'roadtrip.track.errorSave': "บันทึกจุดผ่านทางไม่ได้", + 'roadtrip.track.clear': "ลบจุดผ่านทาง {count} จุด", + 'roadtrip.track.current': "กำลังตามแทร็ก {name}", + 'roadtrip.poi.rest': "จุดพักรถ", + 'roadtrip.poi.campsite': "ลานกางเต็นท์", + 'roadtrip.poi.food': "อาหาร", + 'roadtrip.poi.sights': "สถานที่ท่องเที่ยว", + 'roadtrip.poi.within': "ภายใน", + 'roadtrip.poi.filter': "กรองตามชื่อ", + 'roadtrip.poi.noMatch': "ไม่พบ " + "“{name}”" + " ระหว่างทาง", + 'roadtrip.poi.noneMatchFilters': "ไม่มีสิ่งใดระหว่างทางที่ตรงกับตัวกรองนี้", + 'roadtrip.poi.foundFiltered': "พบ {count} จาก {total} แห่งระหว่างทาง", + 'roadtrip.poi.truncated': "มี {count} ช่วงที่ผลลัพธ์มากเกินกว่าจะแสดงได้ในครั้งเดียว จำกัดขอบเขตการค้นหาเพื่อดูส่วนที่เหลือ", + 'roadtrip.poi.search': "ค้นหา", + 'roadtrip.poi.searching': "กำลังค้นหา {done} จาก {total}", + 'roadtrip.poi.capped': "เส้นทางยาวมาก จึงค้นหาเฉพาะช่วงแรก", + 'roadtrip.poi.partial': "ค้นหา {count} ช่วงไม่ได้ เนื่องจากการค้นหาสถานที่ไม่ตอบกลับ", + 'roadtrip.poi.failed': "การค้นหาสถานที่ไม่ตอบกลับในขณะนี้", + 'roadtrip.poi.empty': "เลือกสิ่งที่ต้องการแล้วค้นหา", + 'roadtrip.poi.add': "เพิ่ม", + 'roadtrip.poi.offRoute': "ห่างจากเส้นทาง {distance}", + 'roadtrip.poi.atStart': "ใกล้จุดเริ่มต้น", + 'roadtrip.poi.alongRoute': "หลังจาก {distance}", + 'roadtrip.poi.clearResults': "ล้างผลลัพธ์", + 'roadtrip.poi.addManual': "เพิ่มเอง", + 'roadtrip.poi.addManualShort': "กำหนดเอง", + 'roadtrip.poi.manualHint': "การค้นหาสถานที่อาจไม่พบทุกจุดชาร์จหรือปั๊ม ค้นหาตามชื่อแล้วระบุตำแหน่งบนเส้นทาง", + 'roadtrip.poi.addBetween': "เพิ่มระหว่าง", + 'roadtrip.poi.manualOffRoute': "ห่างจากเส้นทาง {distance} โปรดตรวจสอบว่าอยู่ในช่วงใด", + 'roadtrip.poi.manualAppend': "ยังไม่มีเส้นทาง จึงเพิ่มไว้ท้ายวันที่ {number}", + 'roadtrip.poi.manualNoResults': "ไม่พบสถานที่", + 'roadtrip.poi.manualNoCoords': "หากไม่มีตำแหน่ง สถานที่นี้จะเพิ่มในรายการสถานที่ของทริปแทนที่จะอยู่บนเส้นทาง เลือกจากการค้นหาด้านบนหรือกรอกพิกัด", + 'roadtrip.summary.distance': "ระยะทาง", + 'roadtrip.summary.driving': "เวลาขับรถ", + 'roadtrip.alt.ask': "เส้นทางอื่น", + 'roadtrip.alt.title': "ตัวเลือกการขับรถในช่วงนี้", + 'roadtrip.alt.loading': "กำลังถามระบบนำทาง…", + 'roadtrip.alt.onlyOne': "มีเส้นทางขับรถที่เหมาะสมเพียงเส้นทางเดียว", + 'roadtrip.alt.failed': "ระบบนำทางไม่ตอบกลับในขณะนี้", + 'roadtrip.alt.current': "ปัจจุบัน", + 'roadtrip.alt.fastest': "เร็วที่สุด", + 'roadtrip.alt.slower': "ช้ากว่า {time}", + 'roadtrip.alt.quicker': "เร็วกว่า {time}", + 'roadtrip.alt.otherEngine': "ใช้เวลาจากระบบนำทางสำหรับการหลีกเลี่ยง ไม่ใช่ระบบหลัก", + 'roadtrip.day': "วันที่ {number}", + 'roadtrip.quietDay.empty': "ยังไม่มีจุดแวะ — วางจุดแวะที่นี่", + 'roadtrip.quietDay.one': "ตอนนี้มีเพียง {name} — วางจุดแวะที่นี่", + 'roadtrip.leg.driveText': "{distance} ใน {time}", + 'roadtrip.day.stopCount': "{count} จุดแวะ", + 'roadtrip.day.fold': "ยุบ", + 'roadtrip.day.folded': "ยุบแล้ว", + 'roadtrip.stop.stayShort': "พัก", + 'roadtrip.stop.fillTitle': "เติมถึง", + 'roadtrip.stop.fillGives': "จากที่นี่ไปได้ประมาณ {distance}", + 'roadtrip.stop.fillNoRange': "กำหนดระยะทางเพื่อดูผล", + 'roadtrip.stop.fillDefault': "ใช้ค่าเริ่มต้นของฉัน", + 'roadtrip.stop.fillSet': "กำหนดระดับการเติมของจุดแวะนี้", + 'roadtrip.leg.pending': "ยังไม่มีเส้นทาง", + 'roadtrip.stop.addTitle': "เพิ่มเป็นจุดแวะ", + 'roadtrip.stop.kind': "ประเภทจุดแวะ", + 'roadtrip.stop.landsOn': "วันที่ {day} จุดแวะที่ {position}", + 'roadtrip.stop.duplicate': "“{name}” อยู่ในทริปนี้แล้ว", + 'roadtrip.stop.moreDetails': "รายละเอียดเพิ่มเติม", + 'roadtrip.stop.stay': "เวลาที่จุดแวะนี้", + 'roadtrip.stop.pinned': "เวลาที่คุณกำหนด", + 'roadtrip.stop.computed': "คำนวณจากการขับรถ", + 'roadtrip.via.hint': "ลากเพื่อปรับเส้นทาง คลิกขวาเพื่อลบ", + 'roadtrip.warn.late': "ถึงช้ากว่าเวลาที่กำหนด {minutes} นาที", + 'roadtrip.warn.overnight': "วันถัดไป", + 'roadtrip.spill.title': "จากวันที่ {number}", + 'roadtrip.spill.departs': "ออกเวลา {time}", + 'roadtrip.summary.stops': "จุดแวะ", + 'roadtrip.stay.add': "เพิ่มเวลาพัก", + 'roadtrip.stay.none': "ไม่พัก", + 'roadtrip.stay.custom': "นาที", + 'roadtrip.stay.arrive': "ถึง", + 'roadtrip.stay.leave': "ออก", + 'roadtrip.alt.noMotorway': "ไม่มีทางด่วน", + 'roadtrip.alt.noToll': "ไม่มีค่าผ่านทาง", + 'roadtrip.alt.noFerry': "ไม่มีเรือเฟอร์รี่", + 'roadtrip.summary.partial': "กำลังคำนวณเวลาขับรถส่วนที่เหลือ", +}; + +export default roadtrip; diff --git a/shared/src/i18n/th/settings.ts b/shared/src/i18n/th/settings.ts new file mode 100644 index 000000000..bca9fe832 --- /dev/null +++ b/shared/src/i18n/th/settings.ts @@ -0,0 +1,588 @@ +import type { TranslationStrings } from '../types'; + +const settings: TranslationStrings = { + 'settings.title': "การตั้งค่า", + 'settings.subtitle': "กำหนดการตั้งค่าส่วนบุคคลของคุณ", + 'settings.tabs.display': "ทั่วไป", + 'settings.tabs.map': "แผนที่", + 'settings.tabs.notifications': "การแจ้งเตือน", + 'settings.tabs.integrations': "การเชื่อมต่อ", + 'settings.plugins.oauth.connected': "เชื่อมต่อแล้ว", + 'settings.plugins.oauth.notConnected': "ไม่ได้เชื่อมต่อ", + 'settings.plugins.oauth.connect': "เชื่อมต่อ", + 'settings.plugins.oauth.disconnect': "ตัดการเชื่อมต่อ", + 'settings.tabs.plugins': "ปลั๊กอิน", + 'settings.plugins.title': "การตั้งค่าปลั๊กอิน", + 'settings.plugins.subtitle': "การตั้งค่าส่วนบุคคลของคุณสำหรับปลั๊กอินที่คุณใช้ (คีย์ API, การตั้งค่า)", + 'settings.plugins.empty': "ไม่มีปลั๊กอินที่ใช้งานอยู่", + 'settings.plugins.saved': "บันทึกการตั้งค่าแล้ว", + 'settings.plugins.requiredMissing': "จำเป็นต้องมี \"{field}\"", + 'settings.pluginActivity.title': "กิจกรรมปลั๊กอิน", + 'settings.pluginActivity.description': "ทุกการกระทำที่ปลั๊กอินทำในนามของคุณ สิ่งใหม่ล่าสุดมาก่อน", + 'settings.pluginActivity.empty': "ยังไม่มีกิจกรรมปลั๊กอิน", + 'settings.pluginActivity.refresh': "รีเฟรช", + 'settings.pluginActivity.columns.plugin': "ปลั๊กอิน", + 'settings.pluginActivity.columns.action': "การดำเนินการ", + 'settings.pluginActivity.columns.resource': "ทรัพยากร", + 'settings.pluginActivity.columns.when': "เมื่อ", + 'settings.pluginActivity.columns.status': "ผลลัพธ์", + 'settings.tabs.account': "บัญชี", + 'settings.tabs.offline': "ออฟไลน์", + 'settings.tabs.about': "เกี่ยวกับ", + 'settings.map': "แผนที่", + 'settings.mapTemplate': "แม่แบบแผนที่", + 'settings.mapTemplatePlaceholder.select': "เลือกเทมเพลต...", + 'settings.mapDefaultHint': "เว้นว่างไว้สำหรับ OpenStreetMap (ค่าเริ่มต้น)", + 'settings.mapHint': "เทมเพลต URL สำหรับชิ้นส่วนแผนที่", + 'settings.mapProvider': "ผู้ให้บริการแผนที่", + 'settings.mapProviderHint': "ส่งผลต่อ Trip Planner และแผนที่การเดินทาง Atlas ใช้ Leaflet เสมอ", + 'settings.mapLeafletSubtitle': "คลาสสิก 2D, ไทล์แรสเตอร์ใด ๆ", + 'settings.mapMapboxSubtitle': "ไทล์เวกเตอร์ สิ่งปลูกสร้าง 3 มิติ และภูมิประเทศ", + 'settings.mapMapLibreSubtitle': "ไทล์เวกเตอร์ OpenFreeMap ไม่มีโทเค็น", + 'settings.mapExperimental': "การทดลอง", + 'settings.mapMapboxToken': "โทเค็นการเข้าถึง Mapbox", + 'settings.mapMapboxTokenHint': "โทเค็นสาธารณะ (pk.*) จาก", + 'settings.mapMapboxTokenLink': "mapbox.com → โทเค็นการเข้าถึง", + 'settings.mapCartoKey': "คีย์ CARTO API", + 'settings.mapCartoKeyHint': "แผนที่ฐาน CARTO จะแสดงลายน้ำโดยไม่มีคีย์ ฟรี ไม่ต้องใช้บัญชี จาก", + 'settings.mapCartoKeyLink': "คีย์ API แผนที่ฐาน carto.com", + 'settings.mapCartoKeyMissing': + "เทมเพลตนี้เป็นแผนที่ฐาน CARTO หากไม่มีคีย์ CARTO จะประทับตรา \"API KEY REQUIRED\" ลงบนทุกไทล์ จนกว่าคุณจะป้อน TREK จะแสดงแผนที่ฐานเริ่มต้นแทน", + 'settings.mapStyle': "รูปแบบแผนที่", + 'settings.mapStylePlaceholder': "เลือกสไตล์ Mapbox", + 'settings.mapStyleHint': "ที่ตั้งไว้ล่วงหน้าหรือ mapbox://styles/USER/ID URL ของคุณเอง", + 'settings.mapOpenFreeMapStylePlaceholder': "เลือกสไตล์ OpenFreeMap", + 'settings.mapOpenFreeMapStyleHint': "เลือกสไตล์ที่ตั้งไว้ล่วงหน้าหรือระบุ URL สไตล์ของ OpenFreeMap สไตล์ OpenFreeMap ใช้งานได้โดยไม่ต้องใช้โทเค็น", + 'settings.map3dBuildings': "สิ่งปลูกสร้าง 3 มิติและภูมิประเทศ", + 'settings.map3dHint': "Pitch + การอัดขึ้นรูปอาคาร 3 มิติจริง — ใช้ได้กับทุกสไตล์ รวมถึงดาวเทียมด้วย", + 'settings.mapHighQuality': "โหมดคุณภาพสูง", + 'settings.mapHighQualityHint': "การลดรอยหยัก + การฉายภาพลูกโลกเพื่อขอบที่คมชัดยิ่งขึ้นและมุมมองโลกที่สมจริง", + 'settings.mapHighQualityWarning': "อาจส่งผลกระทบต่อประสิทธิภาพการทำงานของอุปกรณ์ระดับล่าง", + 'settings.mapTipLabel': "เคล็ดลับ:", + 'settings.mapTip': + "คลิกขวาค้างแล้วลากเพื่อหมุนหรือเอียงแผนที่ คลิกกลางเพื่อเพิ่มสถานที่ (คลิกขวาสงวนไว้สำหรับการหมุน)", + 'settings.saveMap': "บันทึกแผนที่", + 'settings.apiKeys': "คีย์ API", + 'settings.mapsKey': "คีย์ Google Maps API", + 'settings.mapsKeyHint': "สำหรับการค้นหาสถานที่ ต้องใช้ Places API (ใหม่) รับที่ console.cloud.google.com", + 'settings.weatherKey': "คีย์ API ของ OpenWeatherMap", + '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.distance': "หน่วยระยะทาง", + 'settings.timeFormat': "รูปแบบเวลา", + 'settings.bookingLabels': "ป้ายกำกับเส้นทางการจอง", + 'settings.bookingLabelsHint': "แสดงชื่อสถานี/สนามบินบนแผนที่ เมื่อปิด จะแสดงเฉพาะไอคอนเท่านั้น", + 'settings.mapPoiPill': "สำรวจสถานที่บนแผนที่", + 'settings.mapPoiPillHint': + "แสดงแถบหมวดหมู่บนแผนที่การเดินทางเพื่อค้นหาร้านอาหาร โรงแรม และอื่นๆ ในบริเวณใกล้เคียงจาก OpenStreetMap", + 'settings.blurBookingCodes': "รหัสการจองเบลอ", + 'settings.aiAlwaysRetry': "ลองนำเข้าการจองอีกครั้งด้วย AI เสมอ", + 'settings.aiAlwaysRetryHint': "เมื่อตัวแยกวิเคราะห์มาตรฐานไม่สามารถอ่านไฟล์ได้ ให้ลองอีกครั้งโดยอัตโนมัติด้วย AI", + 'settings.optimizeFromAccommodation': "เพิ่มประสิทธิภาพเส้นทางจากที่พัก", + 'settings.optimizeFromAccommodationHint': + "เมื่อเพิ่มประสิทธิภาพของวัน ให้เริ่มต้นเส้นทางที่โรงแรมที่คุณตื่นนอนและสิ้นสุดที่โรงแรมที่คุณเช็คอินในเย็นวันนั้น", + 'settings.notifications': "การแจ้งเตือน", + 'settings.notifyTripInvite': "คำเชิญการเดินทาง", + 'settings.notifyBookingChange': "การเปลี่ยนแปลงการจอง", + 'settings.notifyTripReminder': "การแจ้งเตือนการเดินทาง", + 'settings.notifyTodoDue': "สิ่งที่ต้องทำจะครบกำหนดเร็วๆ นี้", + 'settings.notifyVacayInvite': "คำเชิญรวมปฏิทินวันลา", + 'settings.notifyVacayShare': "การแชร์ปฏิทินวันหยุด", + 'settings.notifyPhotosShared': "รูปภาพที่แชร์ (อิมมิช)", + 'settings.notifyCollabMessage': "ข้อความแชท (ร่วมกัน)", + 'settings.notifyPackingTagged': "รายการจัดกระเป๋า: มีการมอบหมายรายการให้คุณ", + 'settings.notifyWebhook': "การแจ้งเตือนของเว็บฮุค", + 'settings.notifyVersionAvailable': "มีเวอร์ชันใหม่แล้ว", + 'settings.notificationPreferences.email': "อีเมล", + 'settings.notificationPreferences.webhook': "เว็บฮุค", + 'settings.notificationPreferences.inapp': "ในแอป", + 'settings.notificationPreferences.notConfigured': "ยังไม่ได้กำหนดค่า — ตั้งค่าในการตั้งค่าปลั๊กอิน", + 'settings.plugins.actions': "การดำเนินการ", + 'settings.plugins.actions.confirm': "ดำเนินการนี้หรือไม่?", + 'settings.notificationPreferences.sendTest': "ส่งแบบทดสอบ", + 'settings.notificationPreferences.configure': "กำหนดค่า", + 'settings.notificationPreferences.testSuccess': "ส่งการแจ้งเตือนการทดสอบแล้ว", + 'settings.notificationPreferences.testFailed': "การทดสอบล้มเหลว", + 'settings.notificationPreferences.pluginConfigured': "กำหนดค่าแล้ว จัดการข้อมูลประจำตัวในหน้าการตั้งค่าปลั๊กอิน", + 'settings.notificationPreferences.ntfy': "เอ็นทีฟี่", + 'settings.notificationPreferences.noChannels': + "ไม่มีการกำหนดค่าช่องทางการแจ้งเตือน ขอให้ผู้ดูแลระบบตั้งค่าการแจ้งเตือนทางอีเมลหรือเว็บฮุค", + 'settings.webhookUrl.label': "URL ของเว็บฮุค", + 'settings.webhookUrl.placeholder': "https://discord.com/api/webhooks/...", + 'settings.webhookUrl.hint': "ป้อน Discord, Slack หรือ URL เว็บฮุคที่กำหนดเองเพื่อรับการแจ้งเตือน", + 'settings.webhookUrl.saved': "บันทึก URL ของ Webhook แล้ว", + 'settings.webhookUrl.test': "ทดสอบ", + 'settings.webhookUrl.testSuccess': "ส่งเว็บฮุคทดสอบเรียบร้อยแล้ว", + 'settings.webhookUrl.testFailed': "การทดสอบเว็บฮุคล้มเหลว", + 'settings.ntfyUrl.topicLabel': "หัวข้อ NTF", + 'settings.ntfyUrl.topicPlaceholder': "การแจ้งเตือนช่วงระยะการเดินทางของฉัน", + 'settings.ntfyUrl.serverLabel': "URL เซิร์ฟเวอร์ Ntfy (ไม่บังคับ)", + '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': "ทดสอบการส่งการแจ้งเตือน ntfy สำเร็จ", + 'settings.ntfyUrl.testFailed': "ทดสอบการแจ้งเตือน ntfy ล้มเหลว", + 'settings.ntfyUrl.tokenCleared': "ล้างโทเค็นการเข้าถึงแล้ว", + 'settings.notificationsDisabled': + "ไม่ได้กำหนดค่าการแจ้งเตือน ขอให้ผู้ดูแลระบบเปิดใช้งานการแจ้งเตือนทางอีเมลหรือเว็บฮุค", + 'settings.notificationsActive': "ช่องที่ใช้งานอยู่", + 'settings.notificationsManagedByAdmin': "กิจกรรมการแจ้งเตือนได้รับการกำหนดค่าโดยผู้ดูแลระบบของคุณ", + 'settings.on': "เปิด", + 'settings.off': "ปิด", + 'settings.mcp.title': "การกำหนดค่า MCP", + 'settings.mcp.endpoint': "จุดสิ้นสุด MCP", + 'settings.mcp.clientConfig': "การกำหนดค่าไคลเอ็นต์", + 'settings.mcp.clientConfigHint': + "แทนที่ ด้วยโทเค็น API จากรายการด้านล่าง อาจจำเป็นต้องปรับเส้นทางไปยัง npx สำหรับระบบของคุณ (เช่น C:\\PROGRA~1\\nodejs\\npx.cmd บน Windows)", + 'settings.mcp.clientConfigHintOAuth': + "แทนที่ และ ด้วยข้อมูลรับรองที่แสดงในไคลเอ็นต์ OAuth 2.1 ที่คุณสร้างด้านบน mcp-remote จะเปิดเบราว์เซอร์ของคุณเพื่อทำการอนุญาตให้เสร็จสิ้นในครั้งแรกที่คุณเชื่อมต่อ อาจจำเป็นต้องปรับเส้นทางไปยัง npx สำหรับระบบของคุณ (เช่น C:\\PROGRA~1\\nodejs\\npx.cmd บน Windows)", + 'settings.mcp.copy': "คัดลอก", + 'settings.mcp.copied': "คัดลอก!", + 'settings.mcp.apiTokens': "โทเค็น API", + 'settings.mcp.createToken': "สร้างโทเค็นใหม่", + 'settings.mcp.noTokens': "ยังไม่มีโทเค็น สร้างหนึ่งรายการเพื่อเชื่อมต่อไคลเอนต์ MCP", + 'settings.mcp.tokenCreatedAt': "สร้างแล้ว", + 'settings.mcp.tokenUsedAt': "ใช้แล้ว", + 'settings.mcp.deleteTokenTitle': "ลบโทเค็น", + 'settings.mcp.deleteTokenMessage': + "โทเค็นนี้จะหยุดทำงานทันที ไคลเอ็นต์ MCP ใดๆ ที่ใช้งานอยู่จะสูญเสียสิทธิ์ในการเข้าถึง", + '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': + "ลงทะเบียนไคลเอ็นต์ OAuth 2.1 เพื่อให้แอปพลิเคชัน MCP บุคคลที่สาม (Claude Web, Cursor ฯลฯ) เชื่อมต่อได้โดยไม่ต้องใช้โทเค็นแบบคงที่", + 'settings.oauth.createClient': "ไคลเอ็นต์ใหม่", + 'settings.oauth.noClients': "ไม่มีไคลเอ็นต์ OAuth ที่ลงทะเบียน", + 'settings.oauth.clientId': "รหัสไคลเอ็นต์", + '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': "เซสชัน OAuth ที่ใช้งานอยู่", + 'settings.oauth.sessionScopes': "ขอบเขต", + 'settings.oauth.sessionExpires': "หมดอายุ", + 'settings.oauth.revoke': "เพิกถอน", + 'settings.oauth.revokeSession': "เพิกถอนเซสชัน", + 'settings.oauth.revokeSessionMessage': "การดำเนินการนี้จะเพิกถอนการเข้าถึงสำหรับเซสชัน OAuth นี้ทันที", + 'settings.oauth.modal.createTitle': "ลงทะเบียนไคลเอ็นต์ OAuth", + 'settings.oauth.modal.presets': "การตั้งค่าล่วงหน้าอย่างรวดเร็ว", + 'settings.oauth.modal.clientName': "ชื่อแอปพลิเคชัน", + 'settings.oauth.modal.clientNamePlaceholder': "เช่น Claude Web แอป MCP ของฉัน", + 'settings.oauth.modal.redirectUris': "เปลี่ยนเส้นทาง URI", + 'settings.oauth.modal.redirectUrisPlaceholder': "https://your-app.com/callback\nhttps://your-app.com/auth", + 'settings.oauth.modal.redirectUrisHint': + "หนึ่ง URI ต่อบรรทัด HTTPS, Loopback HTTP หรือรูปแบบแอปส่วนตัว (myapp://) ตรงกันทุกประการ ยกเว้นพอร์ตของ URI แบบย้อนกลับ", + 'settings.oauth.modal.scopes': "ขอบเขตที่อนุญาต", + 'settings.oauth.modal.scopesHint': + "list_trips และ get_trip_summary พร้อมใช้งานเสมอ โดยไม่จำเป็นต้องมีขอบเขต พวกเขาปล่อยให้ AI ค้นหารหัสการเดินทางที่จำเป็นเพื่อใช้เครื่องมืออื่น", + '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': "ลงทะเบียนไคลเอ็นต์ OAuth ไม่สำเร็จ", + 'settings.oauth.toast.deleted': "ลบไคลเอ็นต์ OAuth แล้ว", + 'settings.oauth.toast.deleteError': "ลบไคลเอ็นต์ OAuth ไม่สำเร็จ", + 'settings.oauth.toast.revoked': "เซสชันถูกเพิกถอน", + 'settings.oauth.toast.revokeError': "ไม่สามารถเพิกถอนเซสชันได้", + 'settings.oauth.toast.rotateError': "ไม่สามารถหมุนเวียนรหัสลับไคลเอ็นต์", + 'settings.oauth.modal.machineClient': "ไคลเอนต์เครื่อง (ไม่มีการเข้าสู่ระบบเบราว์เซอร์)", + 'settings.oauth.modal.machineClientHint': + "ใช้ client_credentials grant — ไม่จำเป็นต้องใช้ URI การเปลี่ยนเส้นทาง โทเค็นจะออกโดยตรงผ่าน client_id + client_secret และทำหน้าที่เป็นคุณภายในขอบเขตที่เลือก", + 'settings.oauth.modal.machineClientUsage': + "รับโทเค็น: POST /oauth/token พร้อมด้วย grant_type=client_credentials, client_id และ client_secret ไม่มีเบราว์เซอร์ ไม่มีโทเค็นการรีเฟรช", + 'settings.oauth.badge.machine': "เครื่อง", + 'settings.account': "บัญชี", + 'settings.about': "เกี่ยวกับ", + 'settings.about.reportBug': "รายงานข้อผิดพลาด", + 'settings.about.reportBugHint': "พบปัญหา? แจ้งให้เราทราบ", + 'settings.about.featureRequest': "คำขอคุณลักษณะ", + 'settings.about.featureRequestHint': "ขอแนะนำฟีเจอร์ใหม่", + 'settings.about.wikiHint': "เอกสารและคำแนะนำ", + 'settings.about.descriptionManaged': + "TREK ช่วยคุณจัดทริปตั้งแต่ไอเดียแรกไปจนถึงความทรงจำสุดท้าย การวางแผนวัน งบประมาณ รายการสิ่งของที่ต้องเตรียมไป รูปภาพ และอื่นๆ อีกมากมาย รวมอยู่ในที่เดียว", + 'settings.about.sourceTitle': "ซอร์สโค้ด", + 'settings.about.sourceHint': "TREK เป็นโอเพ่นซอร์ส ได้รับใบอนุญาต AGPL-3.0", + 'settings.about.supporters.badge': "ผู้สนับสนุนรายเดือน", + 'settings.about.supporters.title': "เพื่อนร่วมเดินทางสำหรับ TREK", + 'settings.about.supporters.subtitle': + "ขณะที่คุณกำลังวางแผนเส้นทางต่อไป คนเหล่านี้กำลังช่วยวางแผนอนาคตของ TREK การสนับสนุนรายเดือนของพวกเขามุ่งตรงไปสู่การพัฒนาและการใช้งานจริง — ดังนั้น TREK ยังคงเป็น Open Source", + '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': "ทำด้วย", + 'settings.about.madeBy': "โดยมอริซและชุมชนโอเพ่นซอร์สที่กำลังเติบโต", + '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.avatarRemoveError': "การลบล้มเหลว", + 'settings.mfa.title': "การรับรองความถูกต้องด้วยสองปัจจัย (2FA)", + 'settings.mfa.description': + "เพิ่มขั้นตอนที่ 2 เมื่อคุณลงชื่อเข้าใช้ด้วยอีเมลและรหัสผ่าน ใช้แอปตรวจสอบความถูกต้อง (Google Authenticator, Authy ฯลฯ)", + 'settings.mfa.requiredByPolicy': + "ผู้ดูแลระบบของคุณต้องการการรับรองความถูกต้องด้วยสองปัจจัย ตั้งค่าแอปตรวจสอบสิทธิ์ด้านล่างก่อนดำเนินการต่อ", + 'settings.mfa.backupTitle': "รหัสสำรอง", + 'settings.mfa.backupDescription': "ใช้รหัสสำรองแบบครั้งเดียวเหล่านี้หากคุณไม่สามารถเข้าถึงแอปตรวจสอบสิทธิ์ของคุณได้", + 'settings.mfa.backupWarning': "บันทึกรหัสเหล่านี้ทันที แต่ละรหัสสามารถใช้ได้เพียงครั้งเดียวเท่านั้น", + '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': "เปิดใช้งานการรับรองความถูกต้องด้วยสองปัจจัย", + 'settings.mfa.toastDisabled': "การรับรองความถูกต้องด้วยสองปัจจัยถูกปิดใช้งาน", + 'settings.mfa.demoBlocked': "ไม่สามารถใช้ได้ในโหมดสาธิต", + 'settings.currency': "แสดงสกุลเงิน", + 'settings.currencyHint': + "จำนวนเงินในต้นทุนจะแสดงแปลงเป็นสกุลเงินนี้เพื่อแสดงเท่านั้น — จำนวนเงินเดิมไม่มีการเปลี่ยนแปลง", + 'settings.currencyTrip': "สกุลเงินการเดินทาง", + 'settings.passkey.title': "พาสคีย์", + 'settings.passkey.description': + "ลงชื่อเข้าใช้เร็วขึ้นและป้องกันฟิชชิ่งด้วยรหัสผ่าน ไม่ว่าจะเป็นลายนิ้วมือ ใบหน้า PIN หรือคีย์ฮาร์ดแวร์ รหัสผ่านของคุณยังคงเป็นข้อมูลสำรอง", + 'settings.passkey.notConfigured': + "รหัสผ่านถูกเปิดใช้งานแต่ยังไม่ได้กำหนดค่าอย่างสมบูรณ์บนเซิร์ฟเวอร์นี้ ขอให้ผู้ดูแลระบบของคุณตั้งค่าโดเมน WebAuthn", + 'settings.passkey.add': "เพิ่มรหัสผ่าน", + 'settings.passkey.addTitle': "เพิ่มรหัสผ่าน", + 'settings.passkey.passwordPrompt': "ยืนยันรหัสผ่านปัจจุบันของคุณ จากนั้นปฏิบัติตามคำแนะนำของอุปกรณ์", + 'settings.passkey.passwordRequired': "รหัสผ่านปัจจุบันของคุณเป็นสิ่งจำเป็น", + 'settings.passkey.namePlaceholder': "ชื่อ (ไม่บังคับ เช่น \"iPhone\")", + 'settings.passkey.addedToast': "เพิ่มรหัสผ่านแล้ว", + 'settings.passkey.added': "เพิ่มแล้ว", + 'settings.passkey.addError': "ไม่สามารถเพิ่มรหัสผ่าน", + 'settings.passkey.cancelled': "การตั้งค่าพาสคีย์ถูกยกเลิก", + 'settings.passkey.deleted': "นำรหัสผ่านออกแล้ว", + 'settings.passkey.deleteConfirm': "นำรหัสผ่านนี้ออกใช่ไหม ยืนยันด้วยรหัสผ่านของคุณ", + 'settings.passkey.rename': "เปลี่ยนชื่อ", + 'settings.passkey.defaultName': "พาสคีย์", + 'settings.passkey.synced': "ซิงค์แล้ว", + 'settings.passkey.deviceBound': "อุปกรณ์นี้", + 'settings.passkey.lastUsed': "ใช้ครั้งสุดท้าย", + 'settings.passkey.neverUsed': "ไม่เคยใช้", + 'settings.airtrail.title': "แอร์เทรล", + 'settings.airtrail.hint': + "เชื่อมต่ออินสแตนซ์ AirTrail ของคุณเพื่อนำเข้าและซิงค์เที่ยวบิน สร้างคีย์ API ใน AirTrail ภายใต้การตั้งค่า → ความปลอดภัย", + 'settings.airtrail.url': "URL ของอินสแตนซ์", + 'settings.airtrail.apiKey': "คีย์เอพีไอ", + 'settings.airtrail.apiKeyPlaceholder': "คีย์ API ของผู้ถือ", + 'settings.airtrail.apiKeyHint': "สร้างใน AirTrail ภายใต้การตั้งค่า → ความปลอดภัย จัดเก็บแบบเข้ารหัส", + 'settings.airtrail.allowInsecureTls': "อนุญาตใบรับรองที่ลงนามด้วยตนเอง", + 'settings.airtrail.allowInsecureTlsHint': "เปิดใช้งานสำหรับอินสแตนซ์ที่เชื่อถือได้บนเครือข่ายของคุณเองเท่านั้น", + 'settings.airtrail.writeBack': "เขียนการเปลี่ยนแปลงกลับไปที่ AirTrail", + 'settings.airtrail.writeBackHint': + "ปิดโดยค่าเริ่มต้น: AirTrail คือแหล่งที่มาของความจริง และ TREK จะอ่านจากข้อมูลนั้นเท่านั้น เปิดเพื่อส่งการแก้ไขที่ทำใน TREK กลับไปยัง AirTrail", + 'settings.airtrail.connected': "เชื่อมต่อแล้ว", + 'settings.airtrail.notConnected': "ไม่ได้เชื่อมต่อ", + 'settings.airtrail.toast.saved': "บันทึกการเชื่อมต่อ AirTrail แล้ว", + 'settings.airtrail.toast.saveError': "ไม่สามารถบันทึกการเชื่อมต่อได้", + 'settings.airtrail.test.button': "ทดสอบการเชื่อมต่อ", + 'settings.airtrail.test.success': "เชื่อมต่อแล้ว — พบ {count} เที่ยวบิน", + 'settings.airtrail.test.failed': "การเชื่อมต่อล้มเหลว", + 'settings.aiParsing.title': "การแยกวิเคราะห์ AI", + 'settings.aiParsing.hint': + "เลือกโมเดล AI ที่ใช้แยกรายละเอียดการจองจากไฟล์ที่อัปโหลด การตั้งค่านี้มีผลเฉพาะเมื่อผู้ดูแลระบบไม่ได้กำหนดโมเดลสำหรับทั้งอินสแตนซ์", + 'settings.aiParsing.provider': "ผู้ให้บริการ", + 'settings.aiParsing.providerLocal': "ท้องถิ่น (โอลามะ)", + 'settings.aiParsing.providerOpenai': "OpenAI", + 'settings.aiParsing.providerAnthropic': "มานุษยวิทยา", + 'settings.aiParsing.localAdminOnly': + "ตำแหน่งข้อมูลภายใน (Ollama) ได้รับการตั้งค่าครั้งเดียวสำหรับอินสแตนซ์ทั้งหมดในการตั้งค่าผู้ดูแลระบบ คุณยังคงสามารถใช้คีย์ OpenAI หรือ Anthropic ของคุณเองได้ที่นี่", + 'settings.aiParsing.model': "รุ่น", + 'settings.aiParsing.baseUrl': "URL ฐาน", + 'settings.aiParsing.baseUrlHint': "ตำแหน่งที่โมเดลทำงาน — เซิร์ฟเวอร์ Ollama ในเครื่องหรือจุดสิ้นสุดที่เข้ากันได้กับ OpenAI", + 'settings.aiParsing.apiKey': "คีย์เอพีไอ", + 'settings.aiParsing.apiKeyHint': "จัดเก็บแบบเข้ารหัส เว้นว่างไว้เพื่อเก็บคีย์ปัจจุบันไว้", + 'settings.aiParsing.multimodal': "ส่งเอกสารเป็นรูปภาพ", + 'settings.aiParsing.multimodalHint': "สำหรับรุ่นที่มองเห็นได้ — ส่ง PDF ต้นฉบับแทนข้อความที่แยกออกมา", + 'settings.aiParsing.toast.saved': "บันทึกการตั้งค่า AI แล้ว", + 'settings.aiParsing.toast.saveError': "ไม่สามารถบันทึกการตั้งค่า AI", + 'settings.tabs.appearance': "ลักษณะที่ปรากฏ", + 'settings.appearance.theme': "ธีม", + 'settings.appearance.scheme': "โทนสี", + 'settings.appearance.scheme.default': "ค่าเริ่มต้น", + 'settings.appearance.scheme.highContrast': "คอนทราสต์สูง", + 'settings.appearance.scheme.indigo': "สีคราม", + 'settings.appearance.scheme.teal': "นกเป็ดน้ำ", + 'settings.appearance.scheme.rose': "โรส", + 'settings.appearance.scheme.amber': "อำพัน", + 'settings.appearance.scheme.violet': "สีม่วง", + 'settings.appearance.scheme.custom': "กำหนดเอง", + 'settings.appearance.customAccent': "สำเนียงที่กำหนดเอง", + 'settings.appearance.contrastOk': "ความคมชัดที่ดี", + 'settings.appearance.contrastLow': "คอนทราสต์ต่ำ", + 'settings.appearance.readability': "ความสามารถในการอ่าน", + 'settings.appearance.transparency': "ความโปร่งใส", + 'settings.appearance.transparencyHint': + "พื้นผิวโปร่งแสงเหมือนแก้ว ปิดเพื่อให้ได้พื้นหลังทึบและมีคอนทราสต์สูง", + 'settings.appearance.reduceMotion': "ลดการเคลื่อนไหว", + 'settings.appearance.reduceMotionHint': "ลดภาพเคลื่อนไหวและการเปลี่ยนภาพให้เหลือน้อยที่สุด", + 'settings.appearance.density': "ความหนาแน่น", + 'settings.appearance.comfortable': "สะดวกสบาย", + 'settings.appearance.compact': "กะทัดรัด", + 'settings.appearance.textSize': "ขนาดข้อความ", + 'settings.appearance.advancedTextSizes': "ขนาดข้อความขั้นสูง", + 'settings.appearance.hideAdvanced': "ซ่อนขั้นสูง", + 'settings.appearance.tier.title': "ชื่อเรื่อง", + 'settings.appearance.tier.subtitle': "คำบรรยาย", + 'settings.appearance.tier.body': "ร่างกาย", + 'settings.appearance.tier.caption': "คำบรรยายภาพ", + 'settings.appearance.dashboardWidgets': "วิดเจ็ตแดชบอร์ด", + 'settings.appearance.dashboardWidgetsHint': "แสดงหรือซ่อนวิดเจ็ตแดชบอร์ดอย่างเป็นอิสระบนเดสก์ท็อปและอุปกรณ์เคลื่อนที่", + 'settings.appearance.desktop': "เดสก์ท็อป", + 'settings.appearance.mobile': "มือถือ", + 'settings.appearance.widget.sidebar': "แถบด้านข้างขวา", + 'settings.appearance.widget.currency': "สกุลเงิน", + 'settings.appearance.widget.collections': "คอลเลกชัน", + 'settings.appearance.widget.timezones': "เขตเวลา", + 'settings.appearance.widget.upcomingReservations': "การจองที่จะเกิดขึ้น", + 'settings.appearance.widget.atlas': "แอตลาส/ประเทศ", + 'settings.appearance.widget.tripsTotal': "ทริปทั้งหมด", + 'settings.appearance.widget.daysTraveled': "วันเดินทาง", + 'settings.appearance.widget.distanceFlown': "ระยะทางที่บิน", + 'settings.appearance.reset': "รีเซ็ตเป็นค่าเริ่มต้น", + 'settings.appearance.group.belowHero': "ข้างล่างพระเอก.", + 'settings.appearance.group.bottomOfPage': "ด้านล่างของหน้า", + 'settings.appearance.sidebarHint': "คอลัมน์ขวาทั้งหมด ปิดและแผงหน้าปัดตรงกลาง", + 'settings.appearance.densityHint': + "ขนาดกะทัดรัดทำให้ระยะห่างและช่องว่างภายในกระชับขึ้นเพื่อเค้าโครงที่หนาแน่นยิ่งขึ้นซึ่งพอดีกับหน้าจอมากขึ้น", + 'settings.appearance.textSizeAll': "ทุกอย่าง", + 'settings.appearance.perSize': "ปรับขนาดแต่ละขนาดแยกกัน", + 'settings.appearance.size.large': "ใหญ่", + 'settings.appearance.size.medium': "ปานกลาง", + 'settings.appearance.size.normal': "ปกติ", + 'settings.appearance.size.small': "เล็ก", + 'settings.appearance.preview.large': "หัวเรื่องใหญ่", + 'settings.appearance.preview.medium': "คำบรรยายปานกลาง", + 'settings.appearance.preview.normal': "ข้อความเนื้อหาปกติ", + 'settings.appearance.preview.small': "คำบรรยาย/ที่อยู่เล็กๆ", + 'settings.appearance.example.large': "หัวเรื่อง, ตัวเลขใหญ่", + 'settings.appearance.example.medium': "หัวข้อย่อย", + 'settings.appearance.example.normal': "ชื่อสถานที่ คำอธิบาย", + 'settings.appearance.example.small': "ที่อยู่, ป้ายกำกับ", + 'settings.appearance.experimental': "การทดลอง", + 'settings.appearance.mobileNav': "แถบนำทางด้านล่าง", + 'settings.appearance.mobileNav.hint': + "เลือกรายการที่จะปรากฏในแถบและรายการใดอยู่ใต้ \"เพิ่มเติม\" แดชบอร์ดจะอยู่อันดับแรกเสมอ", + 'settings.appearance.mobileNav.inBar': "ในบาร์", + 'settings.appearance.mobileNav.underMore': "ภายใต้ “เพิ่มเติม”", + 'settings.appearance.mobileNav.moreEmpty': "ยังไม่มีอะไรที่นี่ ทุกอย่างลงตัวพอดีในบาร์", + 'settings.appearance.mobileNav.pinned': "ปักหมุดแล้ว", + 'settings.appearance.mobileNav.toMore': "ย้ายไปใต้ \"เพิ่มเติม\"", + 'settings.appearance.mobileNav.toBar': "ย้ายไปที่บาร์", + 'settings.appearance.dashOrder': "ลำดับแดชบอร์ด", + 'settings.appearance.dashOrder.hint': + "จัดลำดับรายการการเดินทางและวิดเจ็ตใหม่บนแดชบอร์ดโทรศัพท์ของคุณ ทริปเด่นจะอยู่ด้านบนเสมอ", + 'settings.appearance.dashOrder.trips': "ทริป", + 'settings.appearance.dashOrder.hidden': "ซ่อนเร้น", + 'settings.general.languageRegion': "ภาษาและภูมิภาค", + 'settings.general.travelMap': "การเดินทางและแผนที่", + 'settings.general.startup': "การเริ่มต้น", + 'settings.startPage': "หน้าเริ่มต้น", + 'settings.startPageDashboard': "แดชบอร์ด", + 'settings.startPageActiveTrip': "การเดินทางที่ใช้งานอยู่", + 'settings.startPageHint': + "TREK เปิดตรงในทริปที่กำลังวิ่งวันนี้หรือทริปถัดไปที่กำลังจะมาถึง นั่นคือการเดินทางเดียวกันกับคุณสมบัติแดชบอร์ด", + 'settings.startTripTab': "แท็บเริ่มต้น", + 'settings.startTripTabHint': + "แท็บการเดินทางจะเปิดขึ้น หากเป็นของส่วนเสริมที่คุณปิดไป มุมมองแผนจะเปิดขึ้นแทน", + + // ── Offline (#1135) ──────────────────────────────────────────────────────── + 'settings.offline.cache.title': "แคชออฟไลน์", + 'settings.offline.mode.title': "โหมดออฟไลน์", + 'settings.offline.mode.force': "บังคับโหมดออฟไลน์", + 'settings.offline.mode.forceHint': + "ทำงานจากข้อมูลแคชเท่านั้นและจัดคิวการเปลี่ยนแปลงของคุณ ปิดเพื่อเชื่อมต่อและซิงค์อีกครั้ง", + 'settings.offline.mode.active': "โหมดออฟไลน์เปิดอยู่ — การเปลี่ยนแปลงของคุณอยู่ในคิวและจะซิงค์เมื่อคุณปิด", + 'settings.offline.prepare.title': "เตรียมความพร้อมสำหรับออฟไลน์", + 'settings.offline.prepare.hint': + "ดาวน์โหลดทุกสิ่งที่คุณต้องการ - ข้อมูลการเดินทาง เอกสาร และไทล์แผนที่ - ก่อนที่คุณจะขาดการเชื่อมต่อ", + 'settings.offline.prepare.button': "ดาวน์โหลดเพื่อใช้แบบออฟไลน์", + 'settings.offline.prepare.running': "กำลังดาวน์โหลด...", + 'settings.offline.prepare.done': "พร้อมสำหรับการใช้งานแบบออฟไลน์", + 'settings.offline.prepare.phase.trips': "ข้อมูลการเดินทาง", + 'settings.offline.prepare.phase.files': "เอกสาร", + 'settings.offline.prepare.phase.tiles': "ไทล์แผนที่", + 'settings.offline.resync': "ซิงค์ใหม่ทันที", + 'settings.offline.resyncing': "กำลังซิงค์...", + 'settings.offline.storage.title': "สิ่งที่จะจัดเก็บแบบออฟไลน์", + 'settings.offline.storage.tiles': "จัดเก็บแผ่นแผนที่แบบออฟไลน์", + 'settings.offline.storage.tilesHint': + "ไทล์แผนที่ใช้พื้นที่เก็บข้อมูลมากที่สุด ปิดตัวเลือกนี้เพื่อเก็บเฉพาะข้อมูลการเดินทางและเอกสารแบบออฟไลน์", + 'settings.offline.storage.tripsTitle': "ทริป", + 'settings.offline.storage.tripOn': "เก็บไว้แบบออฟไลน์", + 'settings.offline.storage.tripOff': "ไม่ได้เก็บไว้", + 'settings.offline.storage.tripFinished': "เสร็จแล้ว เก็บไว้เฉพาะเมื่อคุณเปิดเครื่องเท่านั้น", + 'settings.offline.notice.stored': "จัดเก็บ {count} ทริปไว้ในอุปกรณ์นี้", + 'settings.offline.notice.nothing': "ไม่มีอะไรจะเก็บ เปิดการเดินทางที่คุณต้องการเก็บไว้", + 'settings.offline.notice.busy': "การซิงค์กำลังทำงานอยู่ โปรดลองอีกครั้งในอีกสักครู่", + 'settings.offline.notice.offline': "ไม่มีการเชื่อมต่อ เชื่อมต่อเพื่อจัดเก็บการเดินทางเพื่อการใช้งานแบบออฟไลน์", + 'settings.offline.notice.signedOut': "เซสชั่นของคุณสิ้นสุดลงแล้ว ลงชื่อเข้าใช้อีกครั้งเพื่อซิงค์", + 'settings.offline.notice.failed': "การดาวน์โหลดไม่เสร็จสิ้น ตรวจสอบการเชื่อมต่อของคุณแล้วลองอีกครั้ง", + 'settings.offline.notice.loadFailed': "ไม่สามารถอ่านที่เก็บข้อมูลออฟไลน์ของอุปกรณ์นี้ได้ การล้างแคชมักจะช่วยแก้ไขได้", + 'settings.offline.clear': "ล้างแคช", + 'settings.offline.clearConfirm': "ล้างข้อมูลการเดินทางแบบออฟไลน์ทั้งหมดไหม คุณสามารถซิงค์ใหม่ได้ตลอดเวลาขณะออนไลน์", + 'settings.offline.stats.trips': "ทริปที่แคชไว้", + 'settings.offline.stats.pending': "รอดำเนินการเปลี่ยนแปลง", + 'settings.offline.stats.failed': "การเปลี่ยนแปลงล้มเหลว", + 'settings.offline.stats.conflicts': "ข้อขัดแย้ง", + 'settings.offline.empty': "ยังไม่มีแคชการเดินทาง เชื่อมต่ออินเทอร์เน็ตเพื่อซิงค์", + 'settings.offline.loading': "กำลังโหลด...", + 'settings.offline.conflicts.title': "ข้อขัดแย้งในการซิงค์", + 'settings.offline.conflicts.hint': + "การเปลี่ยนแปลงที่คุณทำขัดแย้งแบบออฟไลน์กับการเปลี่ยนแปลงที่ใหม่กว่าบนเซิร์ฟเวอร์ เลือกเวอร์ชันที่จะเก็บไว้", + 'settings.offline.conflicts.keepMine': "เก็บของฉันไว้", + 'settings.offline.conflicts.keepServer': "เก็บไว้ของพวกเขา", + 'settings.offline.conflicts.mine': "รุ่นของคุณ", + 'settings.offline.conflicts.server': "เวอร์ชันเซิร์ฟเวอร์", + 'settings.offline.conflicts.item': "เปลี่ยนเป็น “{name}”", + 'settings.offline.conflicts.strategyTitle': "เมื่อมีความขัดแย้งเกิดขึ้น", + 'settings.offline.conflicts.strategy.ask': "ถามผมทุกครั้ง.", + 'settings.offline.conflicts.strategy.mine': "คงเวอร์ชันของฉันไว้เสมอ", + 'settings.offline.conflicts.strategy.server': "คงเวอร์ชันเซิร์ฟเวอร์ไว้เสมอ", + 'settings.offline.banner.offline': "ออฟไลน์", + 'settings.offline.banner.forced': "โหมดออฟไลน์", + 'settings.offline.banner.queued': "ออฟไลน์ · {count} อยู่ในคิว", + 'settings.offline.banner.syncing': "กำลังซิงค์ {count}...", + 'settings.offline.banner.failed': "ไม่สามารถซิงค์: {count}", + 'settings.offline.banner.conflicts': "ข้อขัดแย้ง: {count}", + 'settings.alwaysShowRoutes': "แสดงเส้นทางการจองเสมอ", + 'settings.alwaysShowRoutesHint': + "วาดเส้นทางโดยอัตโนมัติสำหรับทุกเที่ยวบิน รถไฟ และการจองอื่นๆ บนแผนที่ โดยไม่จำเป็นต้องเปิดเส้นทางต่อรายการ", + + // Public API keys (Settings -> Integrations) + 'settings.apiKeys.title': "คีย์ API", + 'settings.apiKeys.description': "คีย์สำหรับ API สาธารณะ เพื่อให้ซอฟต์แวร์อื่นสามารถอ่านการเดินทางของคุณได้ อ่านอย่างเดียว: คีย์ไม่สามารถเปลี่ยนแปลงหรือลบสิ่งใดๆ ได้", + 'settings.apiKeys.create': "สร้างคีย์", + 'settings.apiKeys.empty': "ยังไม่มีกุญแจ.. สร้างซอฟต์แวร์หนึ่งเพื่อเชื่อมต่อกับซอฟต์แวร์อื่น", + 'settings.apiKeys.createdAt': "สร้างขึ้น", + 'settings.apiKeys.usedAt': "ใช้ครั้งสุดท้าย", + 'settings.apiKeys.deleteTitle': "ลบคีย์", + 'settings.apiKeys.deleteMessage': "สิ่งใดก็ตามที่ใช้คีย์นี้จะหยุดทำงานทันที สิ่งนี้ไม่สามารถยกเลิกได้", + 'settings.apiKeys.deleted': "ลบคีย์แล้ว", + 'settings.apiKeys.deleteFailed': "ไม่สามารถลบคีย์ได้", + 'settings.apiKeys.createFailed': "ไม่สามารถสร้างคีย์ได้", + 'settings.apiKeys.copy': "คัดลอก", + 'settings.apiKeys.docsHint': "ส่งคีย์เป็น \"Authorization: Bearer ...\" หรือ \"X-API-Key: ...\" ไปที่ /api/v1", + 'settings.apiKeys.modal.createTitle': "สร้างคีย์ API", + 'settings.apiKeys.modal.name': "ชื่อ", + 'settings.apiKeys.modal.namePlaceholder': "เช่น ดาวาริช", + 'settings.apiKeys.modal.nameHint': "สำหรับคุณเท่านั้น ดังนั้นคุณจะจำกุญแจได้ในภายหลัง", + 'settings.apiKeys.modal.creating': "กำลังสร้าง...", + 'settings.apiKeys.modal.create': "สร้าง", + 'settings.apiKeys.modal.createdTitle': "สร้างคีย์ API แล้ว", + 'settings.apiKeys.modal.createdWarning': "คัดลอกคีย์ทันที จะแสดงเพียงครั้งเดียวและไม่สามารถเรียกคืนได้ในภายหลัง", + 'settings.apiKeys.modal.done': "เสร็จแล้ว", + 'settings.routingBase': "เครื่องมือคำนวณเส้นทางของคุณเอง", + 'settings.routingBaseHint': "อินสแตนซ์ OSRM ของคุณเอง หากเว้นว่างจะใช้เซิร์ฟเวอร์สาธารณะ ซึ่งรองรับราวหนึ่งคำขอต่อวินาที — เพียงพอสำหรับหนึ่งวันแต่ค่อนข้างจำกัดสำหรับโรดทริป มีผลหลังรีสตาร์ตเซิร์ฟเวอร์", + 'settings.valhallaBase': "อินสแตนซ์ Valhalla ของคุณเอง", + 'settings.valhallaBaseHint': "โดยค่าเริ่มต้น TREK ใช้ FOSSGIS Valhalla สาธารณะเพื่อหลีกเลี่ยงถนนเก็บค่าผ่านทาง ทางด่วน และเรือเฟอร์รี่ ป้อน URL Valhalla ของคุณเองที่นี่เพื่อใช้แทน หากตั้งค่าเฉพาะอินสแตนซ์เส้นทางแบบกำหนดเอง จะไม่ใช้ Valhalla สาธารณะ หลังป้อน URL แบบกำหนดเอง ให้รีสตาร์ตเซิร์ฟเวอร์และโหลดหน้านี้ใหม่", + 'settings.notifyCollectionInvite': "คำเชิญเข้าคอลเลกชัน", + 'settings.notifySynologySessionCleared': "ล้างเซสชัน Synology แล้ว", + 'settings.notifyPluginNotification': "การแจ้งเตือนจากปลั๊กอิน", + 'settings.notifyReplicaFailure': "การทำสำเนาที่เก็บข้อมูลล้มเหลว", + 'settings.apiScopes.title': "สิ่งที่คีย์นี้อ่านได้", + 'settings.apiScopes.hint': "เปิดทุกอย่างไว้สำหรับคีย์ที่ควรเห็นข้อมูลทั้งหมด สิ่งที่คุณปิดจะถูกปฏิเสธสำหรับคีย์นี้ ไม่ใช่เพียงไม่แสดงในคำตอบ", + 'settings.apiScopes.all': "ทุกอย่าง", + 'settings.apiScopes.noneSelected': "เลือกอย่างน้อยหนึ่งส่วน มิฉะนั้นคีย์จะอ่านข้อมูลไม่ได้เลย", + 'settings.apiScopes.limited': "{count} จาก {total}", + 'settings.apiScopes.trips': "ทริป", + 'settings.apiScopes.days': "วัน", + 'settings.apiScopes.places': "สถานที่", + 'settings.apiScopes.notes': "บันทึกรายวัน", + 'settings.apiScopes.reservations': "การจอง", + 'settings.apiScopes.accommodations': "ที่พัก", + 'settings.apiScopes.travellers': "ผู้ร่วมทริป", + 'settings.apiScopes.bucket-list': "รายการสถานที่อยากไป", + 'settings.apiScopes.stats': "ยอดรวม", + 'settings.apiKeys.endpoint': "ปลายทาง", + 'settings.apiKeys.neverUsed': "ไม่เคยใช้", + 'settings.apiKeys.loadFailed': "ไม่สามารถโหลดคีย์ของคุณได้ โหลดหน้านี้ใหม่เพื่อลองอีกครั้ง", + 'settings.apiKeys.limitReached': "คุณมีคีย์ {max} อัน ซึ่งเป็นจำนวนสูงสุดที่บัญชีหนึ่งมีได้ ลบคีย์ที่ไม่ได้ใช้ออกเพื่อสร้างคีย์ใหม่", + 'settings.apiKeys.copyFailed': "ไม่สามารถคัดลอกได้ เลือกข้อความและคัดลอกด้วยตนเอง", +}; + +export default settings; diff --git a/shared/src/i18n/th/share.ts b/shared/src/i18n/th/share.ts new file mode 100644 index 000000000..6ac6cfabe --- /dev/null +++ b/shared/src/i18n/th/share.ts @@ -0,0 +1,16 @@ +import type { TranslationStrings } from '../types'; + +const share: TranslationStrings = { + 'share.linkTitle': "ลิงก์สาธารณะ", + 'share.linkHint': + "สร้างลิงก์ที่ทุกคนสามารถใช้เพื่อดูการเดินทางนี้โดยไม่ต้องเข้าสู่ระบบ อ่านอย่างเดียว — ไม่สามารถแก้ไขได้", + 'share.createLink': "สร้างลิงก์", + 'share.deleteLink': "ลบลิงก์", + 'share.createError': "ไม่สามารถสร้างลิงก์ได้", + 'share.permMap': "แผนที่และแผน", + 'share.permBookings': "การจอง", + 'share.permPacking': "การบรรจุ", + 'share.permBudget': "ค่าใช้จ่าย", + 'share.permCollab': "แชท", +}; +export default share; diff --git a/shared/src/i18n/th/shared.ts b/shared/src/i18n/th/shared.ts new file mode 100644 index 000000000..4a6ed64c4 --- /dev/null +++ b/shared/src/i18n/th/shared.ts @@ -0,0 +1,21 @@ +import type { TranslationStrings } from '../types'; + +const shared: TranslationStrings = { + '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': "รอดำเนินการ", +}; +export default shared; diff --git a/shared/src/i18n/th/stats.ts b/shared/src/i18n/th/stats.ts new file mode 100644 index 000000000..f6baf3454 --- /dev/null +++ b/shared/src/i18n/th/stats.ts @@ -0,0 +1,13 @@ +import type { TranslationStrings } from '../types'; + +const stats: TranslationStrings = { + 'stats.countries': "ประเทศต่างๆ", + 'stats.cities': "เมือง", + 'stats.trips': "ทริป", + 'stats.places': "สถานที่", + 'stats.worldProgress': "ความก้าวหน้าของโลก", + 'stats.visited': "เยี่ยมชม", + 'stats.remaining': "ที่เหลืออยู่", + 'stats.visitedCountries': "ประเทศที่มาเยือน", +}; +export default stats; diff --git a/shared/src/i18n/th/storage.ts b/shared/src/i18n/th/storage.ts new file mode 100644 index 000000000..bc82ab56b --- /dev/null +++ b/shared/src/i18n/th/storage.ts @@ -0,0 +1,153 @@ +import type { TranslationStrings } from '../types'; + +const storage: TranslationStrings = { + // Field labels/help — these keys are pinned by STORAGE_BACKEND_TYPES in + // @trek/shared (labelKey/helpKey); renaming one breaks the admin form. + 'storage.field.root': "ไดเรกทอรีราก", + 'storage.help.root': "เส้นทางสัมบูรณ์บนเซิร์ฟเวอร์ที่แบ็กเอนด์นี้จัดเก็บออบเจ็กต์", + 'storage.field.endpoint': "URL ปลายทาง", + 'storage.help.endpoint': + "URL พื้นฐานของบริการที่เข้ากันได้กับ S3 เช่น https://s3.example.com หรือ http://127.0.0.1:9000.", + 'storage.field.bucket': "ถัง", + 'storage.field.accessKeyId': "รหัสคีย์การเข้าถึง", + 'storage.field.secretAccessKey': "รหัสการเข้าถึงความลับ", + 'storage.field.region': "ภูมิภาค", + 'storage.help.region': "คงค่าเริ่มต้นไว้ เว้นแต่ผู้ให้บริการของคุณต้องการภูมิภาคเฉพาะ", + 'storage.field.keyPrefix': "คำนำหน้าที่สำคัญ", + 'storage.help.keyPrefix': "คำนำหน้าเพิ่มเติมที่จะเพิ่มให้กับคีย์ของออบเจ็กต์ทุกตัว เช่น trek/prod", + 'storage.field.retries': "ลองอีกครั้ง", + 'storage.field.timeoutMs': "หมดเวลา (มิลลิวินาที)", + 'storage.field.primary': "แบ็กเอนด์หลัก", + 'storage.field.replicas': "แบบจำลอง", + + // Panel chrome + 'storage.title': "ที่เก็บของ", + 'storage.description': "TREK จะจัดเก็บไฟล์ รูปภาพ และข้อมูลสำรองที่อัปโหลดไว้ การเปลี่ยนแปลงจะยังไม่มีผลจนกว่าคุณจะบันทึก", + 'storage.loading': "กำลังโหลด...", + 'storage.saved': "บันทึกการกำหนดค่าพื้นที่เก็บข้อมูลแล้ว", + 'storage.save': "บันทึกการเปลี่ยนแปลง", + 'storage.unsaved': "การเปลี่ยนแปลงที่ไม่ได้บันทึก", + + 'storage.saveConflict': + "การตั้งค่าพื้นที่เก็บข้อมูลมีการเปลี่ยนแปลงตั้งแต่คุณโหลด ดังนั้นการเปลี่ยนแปลงของคุณจึงไม่ได้รับการบันทึก ละทิ้งและโหลดการตั้งค่าที่บันทึกไว้อีกครั้งเพื่อเริ่มต้นใหม่", + 'storage.discardAndReload': "ยกเลิกการเปลี่ยนแปลงของฉันและโหลดซ้ำ", + 'storage.configError.banner': "โหลดการตั้งค่าที่เก็บข้อมูลที่เก็บไว้ไม่สำเร็จ — การบันทึกจะแทนที่: {error}", + // Backends list + 'storage.backends.title': "แบ็กเอนด์", + 'storage.backends.add': "เพิ่มแบ็กเอนด์", + 'storage.backends.usedBy': "ใช้โดย: {categories}", + 'storage.backends.unused': "ไม่ได้รับมอบหมายให้อยู่ในหมวดหมู่ใด ๆ", + 'storage.backends.envReadOnly': "กำหนดโดยตัวแปรสภาพแวดล้อม — อ่านอย่างเดียว", + 'storage.source.built-in': "บิวท์อิน", + 'storage.source.env': "สิ่งแวดล้อม", + 'storage.source.settings': "การตั้งค่า", + 'storage.type.local': "ท้องถิ่น", + 'storage.type.s3': "S3", + 'storage.type.mirror': "กระจกเงา", + 'storage.actions.test': "ทดสอบ", + 'storage.actions.edit': "แก้ไข", + 'storage.actions.remove': "ลบ", + + // Test-connection results + 'storage.test.running': "กำลังทดสอบ...", + 'storage.test.ok': "การเชื่อมต่อตกลง", + 'storage.test.failed': "การทดสอบล้มเหลว", + + // Remove pre-check (friendly message; the server stays authoritative) + 'storage.remove.title': "ลบแบ็กเอนด์", + 'storage.remove.body': + "ลบ {name} ออกจากการกำหนดค่าหรือไม่ เซิร์ฟเวอร์ปฏิเสธการบันทึกหากมีสิ่งใดยังคงขึ้นอยู่กับข้อมูลดังกล่าว", + 'storage.remove.stillAssigned': "ยังคงมอบหมายให้: {categories}", + + // Backend form + 'storage.form.addTitle': "เพิ่มแบ็กเอนด์", + 'storage.form.editTitle': "แก้ไขแบ็กเอนด์", + 'storage.form.name': "ชื่อ", + 'storage.form.type': "ประเภท", + 'storage.form.apply': "สมัคร", + 'storage.form.cancel': "ยกเลิก", + 'storage.form.duplicateName': "มีแบ็กเอนด์ชื่อ {name} อยู่แล้ว", + + // Category map + 'storage.categories.title': "หมวดหมู่", + 'storage.categories.default': "ค่าเริ่มต้น", + 'storage.categories.reassignWarning': + "ออบเจ็กต์ที่มีอยู่จะไม่ย้าย: ออบเจ็กต์ใหม่จะไปที่แบ็กเอนด์ที่เพิ่งกำหนด ส่วนออบเจ็กต์เก่าจะยังคงอยู่ในตำแหน่งเดิม", + 'storage.category.files': "เอกสารการเดินทาง", + 'storage.category.journey': "ภาพถ่ายการเดินทาง", + 'storage.category.covers': "ภาพปก", + 'storage.category.avatars': "รูปโปรไฟล์", + 'storage.category.places': "วางภาพ", + 'storage.category.photos-google': "แคชรูปภาพของ Google", + 'storage.category.photos-trek': "แคชภาพถ่าย TREK", + 'storage.category.backups': "การสำรองข้อมูล", + + // What each category stores — rendered under the label in the category map. + 'storage.categoryDesc.files': + "ไฟล์แนบที่อัปโหลดไปยังการเดินทาง - ตั๋ว, PDF, การยืนยันการจอง และไฟล์ที่แชร์ในแชทการเดินทาง", + 'storage.categoryDesc.journey': "ภาพถ่ายและภาพขนาดย่อที่แนบมากับรายการการเดินทาง", + 'storage.categoryDesc.covers': "ภาพหน้าปกการเดินทางและคอลเลกชัน รวมถึงหน้าปกที่ดึงมาจาก Unsplash", + 'storage.categoryDesc.avatars': "รูปโปรไฟล์บัญชีผู้ใช้", + 'storage.categoryDesc.places': "รูปภาพที่แนบมากับสถานที่และคอลเลกชันสถานที่ — อัปโหลดหรือนำเข้า", + 'storage.categoryDesc.photos-google': "สำเนารูปภาพสถานที่จาก Google ที่แคชไว้ — สร้างใหม่ได้และสามารถลบได้อย่างปลอดภัย", + 'storage.categoryDesc.photos-trek': + "รูปภาพที่แคชไว้จากบริการภาพถ่าย TREK ที่ใช้โดย Memories — สามารถดึงข้อมูลใหม่ได้ ปลอดภัยที่จะสูญหาย", + 'storage.categoryDesc.backups': "คลังสำรองข้อมูลเซิร์ฟเวอร์ที่สร้างโดยแผงสำรองข้อมูลหรือกำหนดการ", + + // Health strip + 'storage.health.title': "สุขภาพ", + 'storage.health.allClear': "ไม่มีการบันทึกความล้มเหลวของการจำลอง", + 'storage.health.seedFile': + "มีไฟล์ seed ของ storage-config.json แต่ถูกละเว้น — มีแถวการกำหนดค่าอยู่แล้ว จัดการพื้นที่เก็บข้อมูลที่นี่", + 'storage.health.failureLine': "{op} จาก {key} บน {backend} ล้มเหลว: {error}", + + // Replicas-on-primary mirror UX (2026-08-20 spec) + 'storage.mirror.targets': "เป้าหมายการจำลอง", + 'storage.mirror.targetsHelp': "ทุกการเขียนไปยังแบ็กเอนด์นี้จะถูกคัดลอกไปยังแต่ละเป้าหมายที่เลือกด้วย", + 'storage.mirror.latencyNote': + "การจำลองจะถูกเขียนทีละรายการในระหว่างการอัปโหลดแต่ละครั้ง - เป้าหมายที่ช้าหรือไม่สามารถเข้าถึงได้จะทำให้การอัปโหลดทุกหมวดหมู่ในแบ็กเอนด์นี้ช้าลง", + 'storage.mirror.mirroredTo': "มิเรอร์ไปที่: {targets}", + 'storage.mirror.replicaOf': "แบบจำลองของ: {primaries}", + 'storage.mirror.cacheWarning': + "ไม่แนะนำ: หมวดหมู่นี้มีเนื้อหาที่สามารถดึงซ้ำได้ — การจำลองเนื้อหามักจะสิ้นเปลือง", + 'storage.mirror.degenerate.duplicate-mirror': + "กระจกบานที่สองล้อมรอบ {primary} - แผงควบคุมจะจัดการเฉพาะกระจกบานแรกเท่านั้น ลบอันนี้เพื่อจัดการการมิเรอร์จาก {primary}", + 'storage.mirror.degenerate.env-primary': "ล้อมแบ็คเอนด์ที่กำหนดโดยสภาพแวดล้อม — ไม่สามารถแก้ไขได้ที่นี่", + 'storage.mirror.degenerate.missing-primary': "อ้างอิงถึงแบ็กเอนด์ที่ไม่มีอยู่อีกต่อไป", + 'storage.remove.usedAsReplicaBy': "ใช้เป็นแบบจำลองโดย: {primaries}", + + // Backfill + usage (backfill/stats/notifications spec) + 'storage.sync.now': "ซิงค์เลย", + 'storage.sync.running': "กำลังซิงค์… {done}/{total}", + 'storage.sync.counts': "{copied} คัดลอกแล้ว · {skipped} ข้าม · {failed} ล้มเหลว", + 'storage.sync.cancel': "ยกเลิกการซิงค์", + 'storage.sync.done': "การซิงค์เสร็จสิ้น: คัดลอก {copied}, {deleted} ลบแล้ว, {failed} ล้มเหลว", + 'storage.sync.cancelled': "การซิงค์ถูกยกเลิก", + 'storage.sync.error': "การซิงค์ล้มเหลว: {error}", + 'storage.sync.prompt': "ออบเจ็กต์ที่มีอยู่ยังไม่ถูกจำลองแบบ — ซิงค์ตอนนี้เลยใช่ไหม", + 'storage.sync.dismiss': "ยกเลิก", + 'storage.usage.line': "{objects} วัตถุ · {size}", + 'storage.usage.computed': "คำนวณการใช้งาน {age}", + 'storage.usage.never': "ยังไม่ได้คำนวณการใช้งาน", + 'storage.usage.refresh': "รีเฟรช", + 'storage.usage.compute': "คำนวณตอนนี้", + 'storage.usage.legacyNote': "รวมถึงคลังภาพดั้งเดิม", + + // Category migration (copy → flip → delta sweep) + 'storage.migrate.promptTitle': "ย้ายวัตถุที่มีอยู่ไปยังแบ็กเอนด์ใหม่หรือไม่", + 'storage.migrate.promptLine': "{category}: {objects} วัตถุ ({size}) จาก {from} ถึง {to}", + 'storage.migrate.promptLineUnknown': "{category}: ไม่ทราบขนาด (ยังไม่มีการสแกนการใช้งาน) จาก {from} ถึง {to}", + 'storage.migrate.move': "ย้ายวัตถุที่มีอยู่", + 'storage.migrate.routeOnly': "เพียงกำหนดเส้นทางการเขียนใหม่", + 'storage.migrate.running': "ย้าย {category}… {done}/{total}", + 'storage.migrate.done': "ย้ายเสร็จแล้ว: {copied} คัดลอก, {skipped} ข้าม", + 'storage.migrate.doneFailures': "{failed} ล้มเหลว — ออบเจ็กต์เหล่านั้นไม่ได้ถูกคัดลอกไปยังแบ็กเอนด์ใหม่", + 'storage.migrate.failed': "การย้ายล้มเหลว: {error} — หมวดหมู่ไม่ได้ถูกเปลี่ยน", + 'storage.migrate.cancelled': "การย้ายถูกยกเลิก — ไม่มีอะไรถูกเปลี่ยน", + 'storage.migrate.reclaimable': "วัตถุ {objects} ({size}) ยังคงอยู่บน {from} — เรียกคืนด้วยตนเอง", + 'storage.migrate.cancel': "ยกเลิกการย้าย", + 'storage.migrate.promptCancel': "ยกเลิก", + 'storage.migrate.queued': "อยู่ในคิว: {categories}", + 'storage.migrate.queueDropped': "ไม่สามารถเริ่มการย้ายข้อมูลครั้งถัดไปได้ - ล้างคิวที่เหลือแล้ว: {categories}", +}; +export default storage; diff --git a/shared/src/i18n/th/system_notice.ts b/shared/src/i18n/th/system_notice.ts new file mode 100644 index 000000000..d987985dd --- /dev/null +++ b/shared/src/i18n/th/system_notice.ts @@ -0,0 +1,84 @@ +import type { TranslationStrings } from '../types'; + +const system_notice: TranslationStrings = { + 'system_notice.v3_photos.title': "รูปภาพได้ย้ายไปอยู่ใน 3.0", + 'system_notice.v3_photos.body': + "**รูปภาพ** ใน Trip Planner ถูกลบออกแล้ว รูปภาพของคุณปลอดภัย — TREK ไม่เคยแก้ไขไลบรารี Immich หรือ Synology ของคุณ\n\nขณะนี้รูปภาพอยู่ในส่วนเสริม **การเดินทาง** การเดินทางเป็นทางเลือก — หากยังไม่พร้อมใช้งาน โปรดขอให้ผู้ดูแลระบบของคุณเปิดใช้งานภายใต้ผู้ดูแลระบบ → ส่วนเสริม", + 'system_notice.v3_journey.title': "พบกับ Journey — บันทึกการเดินทาง", + '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_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_notice.v3_thankyou.title': "บันทึกส่วนตัวจากฉัน", + 'system_notice.v3_thankyou.body': + "ก่อนที่คุณจะไป - ฉันอยากจะใช้เวลาสักครู่\n\nTREK เริ่มต้นจากโปรเจ็กต์เสริมที่ฉันสร้างขึ้นสำหรับการเดินทางของตัวเอง ฉันไม่เคยคิดเลยว่ามันจะเติบโตเป็นสิ่งที่พวกคุณ 4,000 คนไว้วางใจในการวางแผนการผจญภัยของคุณ ดาวทุกดวง ทุกประเด็น ทุกคำขอคุณลักษณะ — ฉันอ่านทั้งหมดแล้ว และพวกมันทำให้ฉันต้องเจอกับช่วงดึกระหว่างงานเต็มเวลากับมหาวิทยาลัย\n\nฉันอยากให้คุณรู้ว่า TREK จะเป็นโอเพ่นซอร์สเสมอ โฮสต์เองเสมอ และเป็นของคุณเสมอ ไม่มีการติดตาม ไม่มีการสมัครสมาชิก ไม่มีการผูกมัดใดๆ เป็นเพียงเครื่องมือที่สร้างขึ้นโดยผู้ที่รักการเดินทางมากเท่ากับคุณ\n\nขอขอบคุณเป็นพิเศษสำหรับ [jubnl](https://github.com/jubnl) — คุณได้กลายเป็นผู้ทำงานร่วมกันที่น่าทึ่ง สิ่งที่ทำให้ 3.0 ยอดเยี่ยมมีมากมายที่ติดอยู่ในลายนิ้วมือของคุณ ขอบคุณที่เชื่อมั่นในโครงการนี้เมื่อยังยากลำบากอยู่\n\nและถึงพวกคุณทุกคนที่แจ้งจุดบกพร่อง แปลสตริง แบ่งปัน TREK กับเพื่อน หรือใช้มันเพื่อวางแผนการเดินทาง — **ขอบคุณ** คุณคือเหตุผลที่มีอยู่\n\nมาร่วมผจญภัยด้วยกันอีกมากมาย\n\n— มอริซ\n\n---\n\n[เข้าร่วมชุมชนบน Discord](https://discord.gg/7Q6M6jDwzf)\n\nหาก TREK ทำให้การเดินทางของคุณดีขึ้น [กาแฟแก้วเล็ก](https://ko-fi.com/mauriceboe) จะเปิดไฟไว้เสมอ", + 'system_notice.v3014_whitespace_collision.title': "จำเป็นต้องดำเนินการ: บัญชีผู้ใช้ขัดแย้งกัน", + 'system_notice.v3014_whitespace_collision.body': + "การอัปเกรด 3.0.14 ตรวจพบชื่อผู้ใช้หรืออีเมลขัดแย้งกันตั้งแต่หนึ่งรายการขึ้นไป ซึ่งเกิดจากการเว้นวรรคนำหน้า/ต่อท้ายในบัญชีที่จัดเก็บไว้ บัญชีที่ได้รับผลกระทบถูกเปลี่ยนชื่อโดยอัตโนมัติ ตรวจสอบบันทึกของเซิร์ฟเวอร์เพื่อหาบรรทัดที่ขึ้นต้นด้วย **[การโยกย้าย] WHITESPACE COLLISION** เพื่อระบุว่าบัญชีใดต้องได้รับการตรวจสอบ", + 'system_notice.welcome_v1.title': "ยินดีต้อนรับสู่ TREK", + 'system_notice.welcome_v1.body': + "นักวางแผนการเดินทางแบบครบวงจรของคุณ สร้างแผนการเดินทาง แบ่งปันการเดินทางกับเพื่อน และจัดระเบียบออนไลน์หรือออฟไลน์", + 'system_notice.welcome_v1.cta_label': "วางแผนการเดินทาง", + 'system_notice.welcome_v1.hero_alt': "จุดหมายปลายทางการเดินทางที่สวยงามพร้อมการซ้อนทับ UI การวางแผน TREK", + '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': "นี่เป็นประกาศการทดสอบสำหรับผู้พัฒนาเท่านั้น", + // Thank-you + support the project (shown once per install and once per upgrade) + 'system_notice.thank_you_support.title': "ขอบคุณที่ใช้ TREK", + 'system_notice.thank_you_support.body': + "ขอขอบคุณอย่างรวดเร็วสำหรับการติดตั้ง TREK — มันมีความหมายมากจริงๆ\n\nฉันเป็นนักพัฒนาเดี่ยวและฉันสร้าง TREK ในเวลาว่าง มันเริ่มต้นจากการเป็นเครื่องมือเล็กๆ น้อยๆ สำหรับการเดินทางของฉันเอง และฉันรู้สึกทึ่งจริงๆ กับการสนับสนุนและความสนใจจากชุมชนตั้งแต่นั้นมา TREK ทำด้วยใจจริงที่อยู่เคียงข้างฉัน — แต่ยังต้องขอบคุณผู้มีส่วนร่วมภายนอกที่น่าทึ่งมากมายที่ช่วยกำหนดรูปแบบนี้\n\n**TREK เป็นโอเพ่นซอร์สและฟรีโดยสมบูรณ์ — และจะคงอยู่เช่นนั้นตลอดไป ไม่มีระดับที่ต้องชำระเงิน ไม่มีการสมัครสมาชิก ไม่มีการจับ ฉันสัญญา.**\n\nหาก TREK มีประโยชน์สำหรับคุณและคุณต้องการสนับสนุนการพัฒนา กาแฟแก้วเล็กๆ ช่วยให้ฉันสร้างได้อย่างแท้จริง — ไม่มีความกดดันเลย แต่ทุกแก้วช่วยให้ค่ำคืนดำเนินต่อไปได้\n\nขอบคุณที่อยู่ที่นี่\n\n— มอริซ", + 'system_notice.thank_you_support.highlight_opensource': "โอเพ่นซอร์ส 100% บน GitHub", + 'system_notice.thank_you_support.highlight_free': "ฟรีตลอดไป — ไม่มีระดับการชำระเงินใด ๆ", + 'system_notice.thank_you_support.highlight_community': "สร้างขึ้นร่วมกับชุมชน", + 'system_notice.thank_you_support.cta_bmc': "ซื้อกาแฟให้ฉัน", + 'system_notice.thank_you_support.cta_kofi': "รองรับ Ko-fi", + 'system_notice.pager.prev': "ประกาศก่อนหน้า", + 'system_notice.pager.next': "ประกาศถัดไป", + 'system_notice.pager.counter': "{current} / {total}", + 'system_notice.pager.goto': "ไปที่ประกาศ {n}", + 'system_notice.pager.position': "ประกาศ {current} จาก {total}", + 'system_notice.release_notes.eyebrow': "ติดตั้งอัปเดตแล้ว", + 'system_notice.release_notes.headline': "สามสิ่งที่ TREK ทำได้ด้วยตัวเองแล้ว", + 'system_notice.release_notes.intro': "API สถานที่ของตัวเอง การวางแผนโรดทริปตั้งแต่ต้นจนจบ และประวัติตำแหน่งของคุณกลับมาอยู่ในมือคุณ", + 'system_notice.release_notes.features_label': "ไฮไลต์สำคัญ", + 'system_notice.release_notes.features_aside': "ไกลจากทุกสิ่ง", + 'system_notice.release_notes.feature_places_title': "TREK Places API", + 'system_notice.release_notes.feature_places_body': "โปรแกรมวางแผนท่องเที่ยวโอเพนซอร์สรายแรกที่โฮสต์ API สถานที่ของตัวเอง 73.6 ล้านสถานที่ สร้างใหม่ทุกเดือน ไม่ต้องมีคีย์ ไม่มีโควตา", + 'system_notice.release_notes.feature_roadtrip_title': "ส่วนเสริมโรดทริป", + 'system_notice.release_notes.feature_roadtrip_body': "โหมดโรดทริปวางแผนการขับรถเอง: เส้นทาง ระยะทาง เวลา และจุดแวะ เป็นส่วนเสริมที่ปิดไว้จนกว่าผู้ดูแลจะเปิดใช้", + 'system_notice.release_notes.feature_dawarich_title': "การเชื่อมต่อ Dawarich", + 'system_notice.release_notes.feature_dawarich_body': "คำตอบแบบโฮสต์เองแทน Google Timeline ซึ่งอ่านได้แล้วใน TREK TREK อ่านอย่างเดียว และจะไม่เขียนข้อมูลกลับ", + 'system_notice.release_notes.footnote': "รวมถึงรายการการเปลี่ยนแปลงเล็ก ๆ อีกยาวเหยียดทั่วทั้ง TREK", + 'system_notice.release_notes.notes_label': "บันทึกประจำรุ่น", + 'system_notice.release_notes.note_eyebrow': "ข้อความจากผู้ดูแลโครงการ", + 'system_notice.release_notes.note_title': "คุณคือเหตุผลที่ผมยังสร้าง TREK ต่อไป", + 'system_notice.release_notes.note_body': "TREK เริ่มจากเครื่องมือเล็ก ๆ สำหรับทริปของผมเอง เขียนหลังเลิกงานเพราะอยากได้วิธีวางแผนที่ดีกว่า มันไม่เคยหยุดเติบโตเลย แทบทุกอย่างที่คุณใช้ถูกสร้างตอนดึก วันหยุด บนรถไฟ ควบคู่กับงานประจำ และมีหลายค่ำคืนที่ผมแอบสงสัยว่าใครสักคนจะเปิดมันใช้หรือไม่", + 'system_notice.release_notes.promise_label': "คำมั่นสัญญา", + 'system_notice.release_notes.promise_lead': "TREK จะฟรีตลอดไป", + 'system_notice.release_notes.promise_text': "ทุกฟีเจอร์ ทุกอัปเดต สำหรับทุกคน ไม่มีระดับแบบเสียเงิน ไม่มีการสมัครสมาชิก ไม่มีเงื่อนไขแอบแฝง", + 'system_notice.release_notes.note_body_after': "แล้วคุณก็ทำเช่นนั้น ภายในไม่กี่เดือนมีคุณหลายพันคน: ดาว รายงานบั๊ก คำแปลในภาษาที่ผมพูดไม่ได้ และ pull request จากผู้คนที่ผมไม่เคยพบ ผมยังตรวจดูคลังโค้ดเป็นสิ่งแรกทุกเช้า และมันก็ยังไม่ค่อยเหมือนเรื่องจริง", + 'system_notice.release_notes.note_closing': "ขอบคุณที่อยู่ตรงนี้ จาก Maurice", + 'system_notice.release_notes.support_lead': "TREK ฟรีและจะฟรีเสมอ แต่เซิร์ฟเวอร์ โดเมน และคืนดึก ๆ มากมายไม่ฟรี", + 'system_notice.release_notes.support_text': "หาก TREK มีที่ในทริปของคุณ ซื้อกาแฟให้ผมสักแก้วและช่วยให้อัปเดตถัดไปเกิดขึ้นได้", + 'system_notice.release_notes.cta_bmc': "ซื้อกาแฟให้ผม", + 'system_notice.release_notes.cta_kofi': "สนับสนุนผ่าน Ko-fi", +}; +export default system_notice; diff --git a/shared/src/i18n/th/todo.ts b/shared/src/i18n/th/todo.ts new file mode 100644 index 000000000..01a18e523 --- /dev/null +++ b/shared/src/i18n/th/todo.ts @@ -0,0 +1,41 @@ +import type { TranslationStrings } from '../types'; + +const todo: TranslationStrings = { + 'todo.emptyFiltered': "ไม่มีงานที่ตรงกับตัวกรองนี้", + 'todo.subtab.packing': "รายการจัดกระเป๋า", + 'todo.subtab.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': "ใหม่", + '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': "สร้างงาน", +}; +export default todo; diff --git a/shared/src/i18n/th/transport.ts b/shared/src/i18n/th/transport.ts new file mode 100644 index 000000000..16dbb7e8b --- /dev/null +++ b/shared/src/i18n/th/transport.ts @@ -0,0 +1,10 @@ +import type { TranslationStrings } from '../types'; + +const transport: TranslationStrings = { + 'transport.addTransport': "เพิ่มการขนส่ง", + 'transport.modalTitle.create': "เพิ่มการขนส่ง", + 'transport.modalTitle.edit': "แก้ไขการขนส่ง", + 'transport.title': "การขนส่ง", + 'transport.addManual': "การขนส่ง", +}; +export default transport; diff --git a/shared/src/i18n/th/trip.ts b/shared/src/i18n/th/trip.ts new file mode 100644 index 000000000..0f0008134 --- /dev/null +++ b/shared/src/i18n/th/trip.ts @@ -0,0 +1,92 @@ +import type { TranslationStrings } from '../types'; + +const trip: TranslationStrings = { + '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.loadingSteps.pack': "กำลังจัดกระเป๋า...", + 'trip.loadingSteps.road': "กำลังออกเดินทาง...", + 'trip.loadingSteps.arrive': "เกือบจะถึงแล้ว...", + 'trip.mobilePlan': "แผน", + 'trip.mobilePlaces': "สถานที่", + 'trip.toast.placeUpdated': "อัปเดตสถานที่แล้ว", + 'trip.toast.tripUpdated': "อัปเดตการเดินทางแล้ว", + '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} แล้ว", + 'trip.invite.linkTitle': "ลิงก์เชิญเข้าร่วมทริป", + 'trip.invite.linkHint': + "ใครก็ตามที่มีบัญชี TREK ที่เปิดลิงก์นี้จะเข้าร่วมการเดินทางในฐานะสมาชิก สร้างใหม่เพื่อทำให้ลิงก์เก่าใช้ไม่ได้", + 'trip.invite.create': "สร้างลิงก์คำเชิญ", + 'trip.invite.regenerate': "สร้างใหม่", + 'trip.invite.disable': "ปิดการใช้งาน", + 'trip.invite.joinHeading': "ร่วมทริปนี้ด้วย", + 'trip.invite.joinPrompt': "คุณได้รับเชิญให้เข้าร่วม \"{title}\"", + 'trip.invite.joinCta': "ร่วมทริป", + 'trip.invite.joining': "กำลังเข้าร่วม...", + 'trip.invite.invalidTitle': "ไม่สามารถเชิญได้", + 'trip.invite.invalid': "ลิงก์คำเชิญนี้ไม่ถูกต้องหรือหมดอายุแล้ว", + 'trip.invite.backToDashboard': "กลับไปที่แดชบอร์ด", + 'transit.title': "การขนส่งสาธารณะ", + 'transit.from': "จาก", + 'transit.to': "ถึง", + 'transit.searchStop': "ค้นหาจุดจอดหรือสถานี...", + 'transit.swap': "สลับ", + 'transit.depart': "ออกเดินทาง", + 'transit.arrive': "มาถึง", + 'transit.mode.rail': "รถไฟ", + 'transit.mode.subway': "รถไฟใต้ดิน", + 'transit.mode.tram': "รถราง", + 'transit.mode.bus': "รถบัส", + 'transit.mode.ferry': "เรือเฟอร์รี่", + 'transit.mode.cable': "เคเบิลคาร์", + 'transit.pref.best': "เส้นทางที่ดีที่สุด", + 'transit.pref.transfers': "เปลี่ยนขบวนน้อยลง", + 'transit.pref.walking': "เดินน้อยลง", + 'transit.search': "ค้นหา", + 'transit.searching': "กำลังค้นหา...", + 'transit.searchError': "การค้นหาเส้นทางล้มเหลว โปรดลองอีกครั้ง", + 'transit.noResults': "ไม่พบการเชื่อมต่อ ลองเวลาหรือตัวกรองอื่น", + 'transit.direct': "โดยตรง", + 'transit.transfers': "เปลี่ยนขบวน {count} ครั้ง", + 'transit.min': "{count} นาที", + 'transit.stops': "{count} ป้าย", + 'transit.walkTo': "เดินไป {name}", + 'transit.platform': "แพลตฟอร์ม {track}", + 'transit.adding': "กำลังเพิ่ม...", + 'transit.addToDay': "เพิ่มไปยังวัน", + 'transit.itinerary': "กำหนดการเดินทาง", + 'transit.attribution': "ข้อมูลเส้นทางผ่าน", + 'transport.modeManual': "กำหนดเอง", + 'transport.modeAutomated': "อัตโนมัติ", + 'transit.sectionTitle': "การขนส่งสาธารณะแบบอัตโนมัติ", + 'transit.changeRoute': "เปลี่ยนเส้นทาง", + 'transit.editDetails': "แก้ไขรายละเอียด", + 'transit.journey': "การเดินทางด้วยรถสาธารณะ", + 'transit.pickDay': "เลือกวันเพื่อค้นหาการเชื่อมต่อ", + 'transit.noItinerary': "รายการนี้ไม่มีแผนการเดินทางที่เก็บไว้ — ใช้ \"เปลี่ยนเส้นทาง\" เพื่อค้นหา", + 'transit.durationLabel': "ระยะเวลา", + 'transit.transfersLabel': "การเปลี่ยนขบวน", + 'transit.walkLabel': "เดิน", + 'transit.searchHint': "ค้นหาการเชื่อมต่อจริงและเพิ่มโดยตรงไปยังวัน — ข้อมูลผ่าน Transitous", + 'trip.toast.loadError': "ไม่สามารถโหลดทริปได้", + 'transit.noResultsVia': "ไม่พบเส้นทางผ่าน {provider} ลองเปลี่ยนเวลาหรือตัวกรอง", +}; +export default trip; diff --git a/shared/src/i18n/th/trips.ts b/shared/src/i18n/th/trips.ts new file mode 100644 index 000000000..977f562f4 --- /dev/null +++ b/shared/src/i18n/th/trips.ts @@ -0,0 +1,16 @@ +import type { TranslationStrings } from '../types'; + +const trips: TranslationStrings = { + 'trips.memberRemoved': "{username} ถูกลบออก", + 'trips.memberRemoveError': "ลบไม่สำเร็จ", + 'trips.memberAdded': "{username} เพิ่มแล้ว", + 'trips.memberAddError': "เพิ่มไม่สำเร็จ", + 'trips.reminder': "คำเตือน", + 'trips.reminderNone': "ไม่มี", + 'trips.reminderDay': "วัน", + 'trips.reminderDays': "วัน", + 'trips.reminderCustom': "กำหนดเอง", + 'trips.reminderDaysBefore': "วันก่อนออกเดินทาง", + 'trips.reminderDisabledHint': "การแจ้งเตือนการเดินทางถูกปิดใช้งาน เปิดใช้งานได้ในผู้ดูแลระบบ > การตั้งค่า > การแจ้งเตือน", +}; +export default trips; diff --git a/shared/src/i18n/th/undo.ts b/shared/src/i18n/th/undo.ts new file mode 100644 index 000000000..2331efa32 --- /dev/null +++ b/shared/src/i18n/th/undo.ts @@ -0,0 +1,24 @@ +import type { TranslationStrings } from '../types'; + +const undo: TranslationStrings = { + 'undo.button': "เลิกทำ", + 'undo.tooltip': "เลิกทำ: {action}", + 'undo.assignPlace': "สถานที่ที่ได้รับมอบหมายในแต่ละวัน", + 'undo.removeAssignment': "สถานที่ที่ถูกลบออกจากวัน", + 'undo.reorder': "สถานที่ที่จัดลำดับใหม่", + 'undo.optimize': "ปรับเส้นทางให้เหมาะสม", + 'undo.deletePlace': "ลบสถานที่แล้ว", + 'undo.deletePlaces': "ลบสถานที่แล้ว", + 'undo.changeCategory': "หมวดหมู่มีการเปลี่ยนแปลง", + 'undo.moveDay': "สถานที่ถูกย้ายไปวันอื่น", + 'undo.lock': "สลับสถานที่ล็อคแล้ว", + 'undo.importGpx': "นำเข้าจีพีเอ็กซ์", + 'undo.importKeyholeMarkup': "การนำเข้า KMZ/KML", + 'undo.importFiles': "การนำเข้าไฟล์", + 'undo.importGoogleList': "การนำเข้า Google Maps", + 'undo.importNaverList': "การนำเข้าแผนที่ Naver", + 'undo.importBooking': "การนำเข้าการยืนยันการจอง", + 'undo.addPlace': "เพิ่มสถานที่แล้ว", + 'undo.done': "เลิกทำ: {action}", +}; +export default undo; diff --git a/shared/src/i18n/th/vacay.ts b/shared/src/i18n/th/vacay.ts new file mode 100644 index 000000000..8f9ef205c --- /dev/null +++ b/shared/src/i18n/th/vacay.ts @@ -0,0 +1,149 @@ +import type { TranslationStrings } from '../types'; + +const vacay: TranslationStrings = { + '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.modeHalf': "ครึ่งวัน", + 'vacay.modeHalfHint': "บันทึกวันหยุดครึ่งวัน", + 'vacay.fullDay': "เต็มวัน", + 'vacay.modeComp': "คอมพ์/เฟล็กซ์", + 'vacay.modeCompHint': "บันทึกวันชดเชย/วันยืดหยุ่น (ไม่หักวันลา)", + 'vacay.compHalf': "ครึ่งวันคอมพ์", + '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.schoolHolidays': "วันหยุดโรงเรียน", + 'vacay.schoolHolidaysHint': "ทำเครื่องหมายวันหยุดโรงเรียนเป็นเลเยอร์ปฏิทินแบบภาพ", + 'vacay.selectCountry': "เลือกประเทศ", + 'vacay.selectRegion': "เลือกภูมิภาค (จำเป็น)", + 'vacay.addCalendar': "เพิ่มปฏิทิน", + 'vacay.calendarLabel': "ป้ายกำกับ (ไม่บังคับ)", + 'vacay.calendarColor': "สี", + 'vacay.noCalendars': "ยังไม่มีปฏิทินวันหยุดเพิ่ม", + 'vacay.noSchoolCalendars': "ยังไม่มีการเพิ่มปฏิทินวันหยุดโรงเรียน", + 'vacay.companyHolidays': "วันหยุดบริษัท", + 'vacay.companyHolidaysHint': "อนุญาตให้ทำเครื่องหมายวันหยุดทั่วทั้งบริษัท", + 'vacay.companyHolidaysNoDeduct': "วันหยุดของบริษัทจะไม่นับรวมกับวันหยุด", + 'vacay.weekStart': "สัปดาห์เริ่มต้นในวัน", + 'vacay.weekStartHint': "เลือกว่าสัปดาห์ตามปฏิทินจะเริ่มต้นในวันจันทร์หรือวันอาทิตย์", + 'vacay.carryOver': "ยกยอด", + 'vacay.carryOverHint': "ดำเนินการวันลาพักร้อนที่เหลืออยู่ในปีหน้าโดยอัตโนมัติ", + 'vacay.carriedOverPrevPeriod': "จากงวดที่แล้ว", + 'vacay.compUsedCount': "{count} วันชดเชย / วันยืดหยุ่น", + 'vacay.yearType': "ปีวันลา", + 'vacay.yearTypeHint': "เมื่อปีการลาของคุณเริ่มต้น — การให้สิทธิ์ การใช้งาน และการยกยอดจะตามมา", + 'vacay.yearTypeCalendar': "ปฏิทิน", + 'vacay.yearTypeFiscal': "การคลัง", + 'vacay.yearTypeAnniversary': "วันที่จ้าง", + 'vacay.yearStartMonth': "เริ่มเดือน", + 'vacay.yearStartDay': "วัน", + 'vacay.hireDate': "วันที่จ้าง", + 'vacay.hireDateHint': "เลือกวันที่เริ่มงานของคุณ — ปีวันลาจะเริ่มในวันดังกล่าวของทุกปี", + 'vacay.yearWindow': "{year}: {window}", + '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': "คุณทั้งคู่จะเห็นรายการวันหยุดทั้งหมดในปฏิทินที่แชร์เพียงปฏิทินเดียว", + 'vacay.fuseInfo2': "ทั้งสองฝ่ายสามารถสร้างและแก้ไขรายการให้กันและกันได้", + 'vacay.fuseInfo3': "ทั้งสองฝ่ายสามารถลบรายการและเปลี่ยนแปลงสิทธิ์วันหยุดได้", + 'vacay.fuseInfo4': "การตั้งค่าต่างๆ เช่น วันหยุดนักขัตฤกษ์และวันหยุดบริษัทจะถูกแชร์", + 'vacay.fuseInfo5': "ฝ่ายใดฝ่ายหนึ่งสามารถยกเลิกการรวมได้ทุกเมื่อ โดยรายการของคุณจะยังคงอยู่", + 'vacay.sharedCalendars': "ปฏิทินที่ใช้ร่วมกัน", + 'vacay.shareCalendar': "แบ่งปันปฏิทิน", + 'vacay.shareCalendarHint': "ให้ผู้ใช้ TREK คนอื่นดูปฏิทินวันหยุดของคุณ ดูอย่างเดียว — ไม่ต้องรวม ไม่ต้องแก้ไข", + 'vacay.sharedWithYou': "แบ่งปันกับคุณ", + 'vacay.youShareWith': "คุณแบ่งปันด้วย", + 'vacay.viewOnly': "ดูเท่านั้น", + 'vacay.share': "แบ่งปัน", + 'vacay.shareSent': "แชร์ปฏิทินแล้ว", + 'vacay.shareFailed': "ไม่สามารถแชร์ปฏิทินได้", + 'vacay.stopSharing': "หยุดแชร์", + 'vacay.showInCalendar': "แสดงในปฏิทิน", + 'vacay.hideFromCalendar': "ซ่อนจากปฏิทิน", + 'vacay.sharedEmpty': "แสดงปฏิทินของคุณให้กันและกันโดยไม่ต้องรวมเข้าด้วยกัน", + 'vacay.sharedLegend': "แชร์ (ดูอย่างเดียว)", + 'schoolCatalog.refreshError': "บันทึกการเปลี่ยนแปลงแล้ว แต่ไม่สามารถรีเฟรชรายการได้ ลองโหลดอีกครั้ง", + 'schoolCatalog.title': "วันหยุดโรงเรียน", + 'schoolCatalog.hint': "จัดการภูมิภาควันหยุดโรงเรียนที่ใช้ร่วมกัน ทุกคนเลือกได้ในการตั้งค่าวันหยุด", + 'schoolCatalog.periodHint': "วันที่รวมทั้งสองวัน เพิ่มช่วงวันหยุดสำหรับแต่ละปีการศึกษา", + 'schoolCatalog.region': "ภูมิภาคหรือเขตการศึกษา", + 'schoolCatalog.name': "ชื่อวันหยุด", + 'schoolCatalog.start': "วันที่เริ่ม", + 'schoolCatalog.end': "วันที่สิ้นสุด", + 'schoolCatalog.addPeriod': "เพิ่มช่วงวันหยุด", + 'schoolCatalog.invalid': "ตรวจสอบชื่อและวันที่", + 'schoolCatalog.discard': "ละทิ้งการเปลี่ยนแปลงที่ยังไม่ได้บันทึกหรือไม่", + 'schoolCatalog.country': "ประเทศ", + 'schoolCatalog.deleteHint': "ลบภูมิภาคออกก่อน ไม่สามารถลบภูมิภาคที่ใช้ในปฏิทินได้", + 'schoolCatalog.deleteCountry': "ลบประเทศ", + 'schoolCatalog.addCountry': "เพิ่มประเทศ", + 'schoolCatalog.code': "รหัสประเทศ (เช่น US)", + 'schoolCatalog.empty': "ยังไม่มีภูมิภาค", + 'schoolCatalog.addRegion': "เพิ่มภูมิภาค", + 'schoolCatalog.offline': "เชื่อมต่ออินเทอร์เน็ตเพื่อจัดการวันหยุดโรงเรียน", + 'schoolCatalog.loadError': "ไม่สามารถโหลดภูมิภาควันหยุดโรงเรียนได้ เปิดการตั้งค่าใหม่เพื่อลองอีกครั้ง", + 'schoolCatalog.retry': "ลองอีกครั้ง", +}; +export default vacay;