ทำไมวันที่และตัวเลขจึงต้องการการปรับให้เข้ากับท้องถิ่น

OpenL Team 10/2/2025

TABLE OF CONTENTS

หากคุณจัดส่งทั่วโลก สตริงเดียวกันสามารถมีความหมายต่างกันสำหรับผู้ใช้ต่างๆ: 12/01/2025, 1.234, 1,234, 12:00, 00:00 ความแตกต่างเล็กน้อยเหล่านี้ไม่ใช่เพียงแค่เรื่องของความสวยงาม—พวกมันส่งผลต่อความเชื่อถือ ความเข้าใจ และแม้กระทั่งการปฏิบัติตามกฎหมาย คู่มือฉบับนี้อธิบายว่าทำไมวันที่และตัวเลขต้องมีการแปลตามท้องถิ่น สิ่งที่เปลี่ยนแปลงจริงๆ ตามท้องถิ่น และวิธีการนำไปใช้ให้ถูกต้องทั่วทั้งผลิตภัณฑ์ของคุณ

สิ่งที่เปลี่ยนแปลงตามท้องถิ่น

  • วันที่: ลำดับ (MDY vs DMY vs YMD), ตัวคั่น, ชื่อเดือน/วัน; บางตลาดใช้ปฏิทินที่ไม่ใช่ปฏิทินเกรกอเรียน
  • เวลา: นาฬิกา 12 ชั่วโมง vs 24 ชั่วโมง, ตัวบ่งชี้ AM/PM, เขตเวลา, กฎการปรับเวลาตามฤดูกาล, วันเริ่มต้นสัปดาห์ (วันอาทิตย์ vs วันจันทร์)
  • ตัวเลข: ตัวคั่นทศนิยม (. vs ,), รูปแบบการจัดกลุ่ม (1,234 vs 1.234 vs 1 234), การจัดกลุ่มแบบอินเดีย (1,23,456), ช่องว่างที่ไม่แตก, รูปแบบเครื่องหมายลบ/บวก (ขีด vs ลบแท้ )
  • สกุลเงิน: สัญลักษณ์ vs รหัส ISO, ตำแหน่งสัญลักษณ์ (นำหน้า/ตามหลัง), ช่องว่างแคบ vs กว้าง, ความแม่นยำของทศนิยม (0, 2, หรือ 3+), การแสดงค่าลบในการบัญชี (เช่น (1 234,56 €))
  • เปอร์เซ็นต์และหน่วย: การเว้นวรรคและตำแหน่งเครื่องหมาย (50% vs 50 %), ชื่อหน่วยตามท้องถิ่น, เมตริก vs อิมพีเรียล

ผลกระทบทางธุรกิจ

  • ความเชื่อถือและการแปลง: ราคา ค่าธรรมเนียม และวันที่ที่ “ดูผิด” ลดการซื้อและเพิ่มการยกเลิก
  • ความเสี่ยงในการดำเนินงาน: วันที่ที่อ่านผิดสามารถเปลี่ยนการจองหรือกำหนดเวลา; ข้อผิดพลาดในการแยกวิเคราะห์ทำให้ใบแจ้งหนี้ การส่งออก และการวิเคราะห์เสียหาย
  • การปฏิบัติตามกฎระเบียบ: เอกสารทางการเงินที่มีรูปแบบผิดสามารถละเมิดกฎการออกใบแจ้งหนี้ ภาษี หรือการรายงาน
  • ภาระงานสนับสนุน: ผู้ใช้เปิดตั๋วเพื่อชี้แจงเวลา สกุลเงิน และการป้อนตัวเลขที่ไม่ตรงกับความคาดหวัง

เหตุการณ์ในโลกจริง

แพลตฟอร์มการจองการเดินทางในยุโรปแสดงวันที่ออกเดินทางเป็น 01/03/2024 โดยไม่มีบริบทของท้องถิ่น ลูกค้าสหรัฐฯ ตีความว่าเป็น “วันที่ 3 มกราคม” ในขณะที่ลูกค้าในสหราชอาณาจักรและยุโรปอ่านว่า “วันที่ 1 มีนาคม”

ผลกระทบ:

  • 12% ของการจองระหว่างประเทศถูกทำในวันที่ผิด
  • ฝ่ายบริการลูกค้าได้รับตั๋วคำชี้แจงมากกว่า 3,400 ใบในหนึ่งสัปดาห์
  • $2.3M ในการคืนเงินและค่าธรรมเนียมการจองใหม่
  • 8% ของลูกค้าที่ได้รับผลกระทบเปลี่ยนไปใช้คู่แข่ง

สาเหตุหลัก: รูปแบบ DD/MM/YYYY ที่ถูก hard-coded ในการยืนยันทางอีเมล ในขณะที่เว็บไซต์ใช้ MM/DD/YYYY สำหรับผู้ใช้ในสหรัฐอเมริกา การแก้ไขใช้เวลาเพียง 3 ชั่วโมงของวิศวกร—ความคลุมเครือนี้มีค่าใช้จ่ายมากกว่า 800 เท่าของการป้องกัน

บทเรียน: วันที่ที่ไม่มีบริบทเป็นระเบิดเวลาสำหรับผลิตภัณฑ์ระดับโลกใดๆ

ข้อผิดพลาดทั่วไป

  • รูปแบบที่ถูก hard-coded: MM/DD/YYYY หรือ 1,234.56 ที่ฝังอยู่ใน UI, อีเมล, PDF หรือการส่งออก CSV
  • การจัดเก็บสตริงที่แปลแล้ว: การบันทึก “Dec 1, 2025” แทนที่จะเป็นเวลา ISO ทำให้เกิดข้อผิดพลาดในการแยกวิเคราะห์และการล่องลอยของเขตเวลา
  • การแยกวิเคราะห์ที่ไร้เดียงสา: การใช้ค่าเริ่มต้นของเซิร์ฟเวอร์; การสันนิษฐานตัวคั่นหรือนาฬิกา 12/24 ชั่วโมง
  • การต่อสตริง: การสร้าง “amount + currency” เช่น "$" + 1234.56 แทนการจัดรูปแบบตามท้องถิ่น
  • ความคลุมเครือของเขตเวลา: การแสดงเวลาท้องถิ่นโดยไม่มีเขตที่ชัดเจนสำหรับการดำเนินการที่ไวต่อเวลา
  • ความไม่สอดคล้องกันของเบราว์เซอร์: Safari, Firefox และ Chrome อาจจัดรูปแบบวันที่/ตัวเลขต่างกัน; ทดสอบเสมอในเบราว์เซอร์เป้าหมายทั้งหมด
  • ช่องว่างในการเรนเดอร์ฝั่งเซิร์ฟเวอร์: Node.js ที่ไม่มีข้อมูล ICU เต็มรูปแบบ (node --with-intl=full-icu) ผลิตการจัดรูปแบบที่ไม่สมบูรณ์หรือไม่ถูกต้อง
  • กับดักประสิทธิภาพ: การสร้างอินสแตนซ์ใหม่ Intl.* ในลูปหรือรอบการเรนเดอร์แทนการแคชตัวจัดรูปแบบ

แนวทางปฏิบัติที่ดีที่สุด

  • เก็บค่ามาตรฐาน: วันที่/เวลาเป็น ISO‑8601 ใน UTC; เงินเป็นหน่วยย่อย (เซนต์) หรือทศนิยมความแม่นยำสูง
  • แสดงผลตามท้องถิ่นของผู้ใช้: ใช้ API ที่รับรู้ท้องถิ่น (เช่น Intl.DateTimeFormat, Intl.NumberFormat) สำหรับการแสดงผล
  • ตรวจสอบและแยกวิเคราะห์ตามท้องถิ่น: ยอมรับอินพุตท้องถิ่นเมื่อเหมาะสม; แสดงตัวอย่าง/ตัวอย่างเพื่อแนะนำผู้ใช้
  • ระบุเวลาอย่างชัดเจน: แสดงตัวย่อหรือการชดเชยของเขตเวลา; อนุญาตให้ผู้ใช้เลือกเมื่อผลลัพธ์ขึ้นอยู่กับเวลา
  • ความชัดเจนของสกุลเงิน: ใช้รหัส ISO เมื่อมีความคลุมเครือ; เคารพการวางสัญลักษณ์และการเว้นวรรคตามท้องถิ่น
  • การจัดรูปแบบแบบรวมศูนย์: ชั้นยูทิลิตี้หนึ่งสำหรับทุกพื้นผิว (UI, อีเมล, PDF, ส่งออก) เพื่อให้แน่ใจว่ามีความสอดคล้อง
  • แคชตัวจัดรูปแบบ: การเรียกตัวสร้าง Intl.* มีค่าใช้จ่ายสูง; สร้างครั้งเดียวและใช้ซ้ำอินสแตนซ์ต่อท้องถิ่น

เมื่อไม่ต้องแปลตามท้องถิ่น

ไม่ใช่ทุกอย่างที่ควรแปลตามท้องถิ่น นี่คือสถานการณ์ที่รูปแบบที่อ่านได้โดยเครื่องที่สอดคล้องกันดีกว่า:

  • การส่งออกที่อ่านได้โดยเครื่อง: ไฟล์ CSV ที่ใช้โดยท่อข้อมูลหรือเครื่องมือวิเคราะห์ควรใช้รูปแบบคงที่ (เช่น วันที่ ISO-8601, จุดเป็นตัวคั่นทศนิยม) เอกสารรูปแบบนี้อย่างชัดเจนในส่วนหัวของการส่งออกหรือไฟล์ README
  • การตอบสนองของ API: REST/GraphQL API ควรส่งคืนวันที่เป็นสตริง ISO-8601 และตัวเลขในรูปแบบ JSON มาตรฐาน ให้ลูกค้าจัดการการแปลตามท้องถิ่นตามความชอบของผู้ใช้
  • บันทึกภายในและเมตริก: บันทึก, แดชบอร์ดการตรวจสอบ, และการสืบค้นฐานข้อมูลได้รับประโยชน์จากรูปแบบที่สอดคล้องกันสำหรับการแยกวิเคราะห์, การรวม, และการแจ้งเตือน ใช้ ISO-8601 และรูปแบบตัวเลขมาตรฐาน
  • ตัวระบุที่เป็นมาตรฐาน: รหัสธุรกรรม, หมายเลขคำสั่งซื้อ, หรือการอ้างอิงที่ผู้ใช้อาจต้องสื่อสารข้ามท้องถิ่นควรหลีกเลี่ยงการจัดรูปแบบเฉพาะท้องถิ่น

กฎทั่วไป: แปลสำหรับมนุษย์ที่อ่านเนื้อหา; ใช้รูปแบบมาตรฐานสำหรับเครื่องที่ประมวลผลข้อมูล

แผนการดำเนินการ

  1. ตรวจสอบพื้นผิว: วันที่, เวลา, ตัวเลข, สกุลเงินใน UI, อีเมล, PDFs, การส่งออก CSV/Excel, การวิเคราะห์, บันทึก
  2. กำหนดพื้นที่: รายการพื้นที่ที่รองรับและการสำรองข้อมูลเริ่มต้น; ระบุนโยบาย 12/24 ชั่วโมงต่อพื้นที่
  3. สร้างยูทิลิตี้: ห่อ Intl.* APIs (หรือไลบรารี) ด้วยตัวช่วยและการทดสอบที่ใช้ร่วมกัน; ดำเนินการแคชการจัดรูปแบบ
  4. กลยุทธ์การป้อนข้อมูล: อัปเดตแบบฟอร์มเพื่อยอมรับและตรวจสอบรูปแบบพื้นที่; เก็บค่ามาตรฐานพร้อมกับข้อมูลดิบ
  5. กฎเนื้อหา: จัดทำเอกสารสไตล์สำหรับวันที่สั้น/ยาว, วันที่สัมพันธ์, การแสดงสกุลเงิน, และการจัดรูปแบบเปอร์เซ็นต์
  6. การเปิดตัว: แปลงพื้นผิวที่มีการเข้าชมสูงและมีความเสี่ยงสูงก่อน; ส่งเบื้องหลังฟีเจอร์แฟล็กหากจำเป็น

กลยุทธ์การทดสอบ

นอกเหนือจาก QA ด้วยตนเอง ให้ดำเนินการทดสอบอัตโนมัติเพื่อป้องกันการถดถอย:

  • การทดสอบสแนปชอต: แช่แข็งผลลัพธ์ที่จัดรูปแบบสำหรับแต่ละพื้นที่ที่รองรับ การเปลี่ยนแปลงจะกระตุ้นการตรวจสอบเพื่อให้แน่ใจว่ามีเจตนา
  • การทดสอบแบบรอบทริป: ตรวจสอบว่า format → parse → format ให้ผลลัพธ์ที่เสถียร จับการสูญเสียความแม่นยำหรือรูปแบบที่ไม่ชัดเจน
  • กรณีขอบ: ทดสอบตัวเลขติดลบ, ศูนย์, ตัวเลขขนาดใหญ่มาก (พันล้าน/ล้านล้าน), การเปลี่ยนแปลง DST, ปีอธิกสุรทิน, และวันที่ขอบเขต (1 ม.ค., 31 ธ.ค.)
  • การตรวจสอบข้ามเบราว์เซอร์: การทดสอบอัตโนมัติบน Chrome, Firefox, Safari, และ Edge เพื่อตรวจจับความแตกต่างในการแสดงผล
  • การสำรองข้อมูลพื้นที่: ตรวจสอบการเสื่อมสภาพอย่างราบรื่นเมื่อมีการร้องขอพื้นที่ที่ไม่รองรับ
  • เกณฑ์มาตรฐานประสิทธิภาพ: วัดต้นทุนการสร้างตัวจัดรูปแบบ; ตรวจสอบให้แน่ใจว่าการแคชทำงานในสภาพแวดล้อมการผลิต

เคล็ดลับประสิทธิภาพ

Intl.* APIs ทรงพลังแต่สามารถช้าได้หากใช้งานผิดวิธี ปฏิบัติตามแนวทางเหล่านี้:

// ❌ ไม่ดี: สร้างตัวจัดรูปแบบใหม่ทุกครั้งที่เรียก
function formatPrice(amount, locale) {
  return new Intl.NumberFormat(locale, { 
    style: 'currency', 
    currency: 'USD' 
  }).format(amount);
}

// ✅ GOOD: Cache formatters per locale
const formatters = new Map();
function getFormatter(locale) {
  if (!formatters.has(locale)) {
    formatters.set(locale, new Intl.NumberFormat(locale, { 
      style: 'currency', 
      currency: 'USD' 
    }));
  }
  return formatters.get(locale);
}

function formatPrice(amount, locale) {
  return getFormatter(locale).format(amount);
}
  • แคชอินสแตนซ์ของฟอร์แมตเตอร์: การสร้าง Intl.* มีค่าใช้จ่ายสูง (~1–5ms); การจัดรูปแบบด้วยอินสแตนซ์ที่มีอยู่แล้วรวดเร็ว (~0.01ms)
  • หลีกเลี่ยงลูป: อย่าสร้างฟอร์แมตเตอร์ภายใน map(), forEach(), หรือลูปการเรนเดอร์
  • โหลดข้อมูลท้องถิ่นแบบ Lazy-load: สำหรับเว็บแอป ให้พิจารณาการแยกโค้ดเพื่อโหลดเฉพาะท้องถิ่นที่จำเป็น ลดขนาดบันเดิล
  • ฝั่งเซิร์ฟเวอร์: ใช้ฟอร์แมตเตอร์เดียวต่อรอบการร้องขอ/ตอบกลับ; หลีกเลี่ยงการสร้างต่อรายการในชุดข้อมูลขนาดใหญ่

รายการตรวจสอบ QA

  • วันที่ไม่คลุมเครือใน en-US, en-GB, de-DE, fr-FR, hi-IN, ja-JP, ar-EG
  • เวลาใช้รูปแบบ 12/24 ชั่วโมงที่ถูกต้อง; ตัวบ่งชี้ AM/PM ปรากฏตามที่คาดหวัง; โซนเวลาปรากฏในกระบวนการที่สำคัญต่อเวลา
  • ตัวเลขใช้ตัวคั่นทศนิยมและกลุ่มที่ถูกต้อง; เว้นวรรคที่ไม่แตกหักตามมาตรฐาน (เช่น fr-FR)
  • สกุลเงินแสดงสัญลักษณ์/รหัสที่ถูกต้อง, ตำแหน่ง, และความละเอียดทศนิยมสำหรับแต่ละท้องถิ่น; แสดงค่าลบอย่างถูกต้อง
  • อินพุตยอมรับและแยกวิเคราะห์ข้อมูลท้องถิ่นของผู้ใช้ (หรือบังคับใช้รูปแบบที่รองรับอย่างชัดเจน); ข้อความการตรวจสอบความถูกต้องรับรู้ท้องถิ่น
  • การส่งออก (CSV/PDF) ตรงกับความคาดหวังของท้องถิ่นหรือเอกสารรูปแบบคงที่สำหรับการบริโภคของเครื่องอย่างชัดเจน
  • ข้ามเบราว์เซอร์: วันที่, เวลา, และตัวเลขแสดงผลสม่ำเสมอบน Chrome, Firefox, Safari, และ Edge
  • ประสิทธิภาพ: ไม่มีการสร้างฟอร์แมตเตอร์ในลูป; อินสแตนซ์ที่แคชถูกใช้ซ้ำในการเรนเดอร์

ตัวอย่างโค้ด

JavaScript

// Dates
const date = new Date('2025-01-12T00:00:00Z');

console.log(new Intl.DateTimeFormat('en-US', { dateStyle: 'short', timeZone: 'UTC' }).format(date));
// → 1/12/25

```javascript
console.log(new Intl.DateTimeFormat('en-GB', { dateStyle: 'short', timeZone: 'UTC' }).format(date));
// → 12/01/2025 (day/month/year)

console.log(new Intl.DateTimeFormat('ja-JP', { dateStyle: 'medium', timeZone: 'UTC' }).format(date));
// → 2025/01/12

// Times with timezone display
const time = new Date('2025-01-12T18:05:00Z');

console.log(new Intl.DateTimeFormat('en-US', { 
  dateStyle: 'short',
  timeStyle: 'short', 
  timeZone: 'America/New_York',
  timeZoneName: 'short' 
}).format(time));
// → 1/12/25, 1:05 PM EST

console.log(new Intl.DateTimeFormat('de-DE', { 
  timeStyle: 'short', 
  timeZone: 'Europe/Berlin', 
  hour12: false 
}).format(time));
// → 19:05

// Numbers
const n = 1234.56;
console.log(new Intl.NumberFormat('en-US').format(n)); // → 1,234.56
console.log(new Intl.NumberFormat('de-DE').format(n)); // → 1.234,56
console.log(new Intl.NumberFormat('fr-FR').format(n)); // → 1 234,56 (NBSP as group separator)

// Indian numbering
console.log(new Intl.NumberFormat('hi-IN').format(1234567.89)); // → 12,34,567.89

// Currency
console.log(new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }).format(n));
// → $1,234.56

console.log(new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(n));
// → 1.234,56 €

console.log(new Intl.NumberFormat('ja-JP', { style: 'currency', currency: 'JPY' }).format(1234));
// → ¥1,234 (no decimals)

// Percent and units
console.log(new Intl.NumberFormat('en-US', { style: 'percent', maximumFractionDigits: 0 }).format(0.5));
// → 50%
console.log(new Intl.NumberFormat('fr-FR', { style: 'percent', maximumFractionDigits: 0 }).format(0.5));
// → 50 %

// Formatter caching example
class LocaleFormatter {
  constructor() {
    this.cache = new Map();
  }

  getDateFormatter(locale, options) {
    const key = `date:${locale}:${JSON.stringify(options)}`;
    if (!this.cache.has(key)) {
      this.cache.set(key, new Intl.DateTimeFormat(locale, options));
    }
    return this.cache.get(key);
  }
formatDate(date, locale, options = { dateStyle: 'medium' }) {
    return this.getDateFormatter(locale, options).format(date);
  }
}

const formatter = new LocaleFormatter();
console.log(formatter.formatDate(new Date(), 'en-US')); // → Jan 12, 2025
console.log(formatter.formatDate(new Date(), 'fr-FR')); // → 12 janv. 2025

Python

from babel.dates import format_date, format_time, format_datetime
from babel.numbers import format_number, format_currency, format_percent
from datetime import datetime
import pytz

# Dates
date = datetime(2025, 1, 12)
print(format_date(date, format='short', locale='en_US'))  # → 1/12/25
print(format_date(date, format='short', locale='en_GB'))  # → 12/01/2025
print(format_date(date, format='medium', locale='ja_JP')) # → 2025/01/12

# Times with timezone
tz_ny = pytz.timezone('America/New_York')
tz_berlin = pytz.timezone('Europe/Berlin')
time = datetime(2025, 1, 12, 18, 5, tzinfo=pytz.UTC)

print(format_datetime(time.astimezone(tz_ny), 'short', tzinfo=tz_ny, locale='en_US'))
# → 1/12/25, 1:05 PM

print(format_time(time.astimezone(tz_berlin), format='short', tzinfo=tz_berlin, locale='de_DE'))
# → 19:05

# Numbers
n = 1234.56
print(format_number(n, locale='en_US'))    # → 1,234.56
print(format_number(n, locale='de_DE'))    # → 1.234,56
print(format_number(n, locale='fr_FR'))    # → 1 234,56

# Indian numbering
print(format_number(1234567.89, locale='hi_IN'))  # → 12,34,567.89

# Currency
print(format_currency(n, 'USD', locale='en_US'))  # → $1,234.56
print(format_currency(n, 'EUR', locale='de_DE'))  # → 1.234,56 €
print(format_currency(1234, 'JPY', locale='ja_JP')) # → ¥1,234

# Percent
print(format_percent(0.5, locale='en_US'))  # → 50%
print(format_percent(0.5, locale='fr_FR'))  # → 50 %

Java

import java.text.NumberFormat;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;
import java.util.Currency;

// Dates
ZonedDateTime date = ZonedDateTime.of(2025, 1, 12, 0, 0, 0, 0, ZoneId.of("UTC"));

DateTimeFormatter usFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
    .withLocale(Locale.US);
System.out.println(usFormatter.format(date)); // → 1/12/25

DateTimeFormatter gbFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT)
    .withLocale(Locale.UK);
System.out.println(gbFormatter.format(date)); // → 12/01/2025

DateTimeFormatter jpFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
    .withLocale(Locale.JAPAN);
System.out.println(jpFormatter.format(date)); // → 2025/01/12

// Times
ZonedDateTime time = ZonedDateTime.of(2025, 1, 12, 18, 5, 0, 0, ZoneId.of("UTC"));
ZonedDateTime timeNY = time.withZoneSameInstant(ZoneId.of("America/New_York"));

DateTimeFormatter usTimeFormatter = DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
    .withLocale(Locale.US);
System.out.println(usTimeFormatter.format(timeNY)); // → 1:05 PM

// Numbers
double n = 1234.56;
NumberFormat usFormat = NumberFormat.getInstance(Locale.US);
System.out.println(usFormat.format(n)); // → 1,234.56

NumberFormat deFormat = NumberFormat.getInstance(Locale.GERMANY);
System.out.println(deFormat.format(n)); // → 1.234,56

NumberFormat frFormat = NumberFormat.getInstance(Locale.FRANCE);
System.out.println(frFormat.format(n)); // → 1 234,56

// Currency
NumberFormat usCurrency = NumberFormat.getCurrencyInstance(Locale.US);
usCurrency.setCurrency(Currency.getInstance("USD"));
System.out.println(usCurrency.format(n)); // → $1,234.56

NumberFormat deCurrency = NumberFormat.getCurrencyInstance(Locale.GERMANY);
deCurrency.setCurrency(Currency.getInstance("EUR"));
System.out.println(deCurrency.format(n)); // → 1.234,56 €

NumberFormat jpCurrency = NumberFormat.getCurrencyInstance(Locale.JAPAN); jpCurrency.setCurrency(Currency.getInstance(“JPY”)); System.out.println(jpCurrency.format(1234)); // → ¥1,234


### Go

```go
package main

import (
    "fmt"
    "time"
    "golang.org/x/text/language"
    "golang.org/x/text/message"
    "golang.org/x/text/number"
)

func main() {
    // Numbers
    n := 1234.56

    pUS := message.NewPrinter(language.AmericanEnglish)
    fmt.Println(pUS.Sprintf("%.2f", n)) // → 1,234.56

    pDE := message.NewPrinter(language.German)
    fmt.Println(pDE.Sprintf("%.2f", n)) // → 1.234,56

    pFR := message.NewPrinter(language.French)
    fmt.Println(pFR.Sprintf("%.2f", n)) // → 1 234,56

    // Currency (using number package)
    fmt.Println(pUS.Sprint(number.Decimal(n, number.Scale(2))))  // → 1,234.56

    // Dates - Go's time package uses layouts instead of locale formatting
    // For full i18n date formatting, use github.com/goodsign/monday or similar
    date := time.Date(2025, 1, 12, 0, 0, 0, 0, time.UTC)
    fmt.Println(date.Format("01/02/2006")) // US: 01/12/2025
    fmt.Println(date.Format("02/01/2006")) // EU: 12/01/2025
    fmt.Println(date.Format("2006/01/02")) // ISO: 2025/01/12
}

หมายเหตุ: ไลบรารีมาตรฐานของ Go มีการสนับสนุน locale จำกัด สำหรับการใช้งานในโปรดักชั่น พิจารณา:

แหล่งข้อมูลที่มีประโยชน์

  • มาตรฐาน: Unicode CLDR (มาตรฐานข้อมูลท้องถิ่น), IETF BCP 47 (ตัวระบุท้องถิ่น)
  • เอกสาร: MDN Intl Reference
  • ไลบรารี:
    • Luxon (ไลบรารีวันที่/เวลาแบบสมัยใหม่พร้อม i18n)
    • date-fns พร้อมโมดูลท้องถิ่น
    • Globalize.js (i18n ครอบคลุมตาม CLDR)
    • Format.js (i18n ที่เน้น React พร้อมไวยากรณ์ข้อความ ICU)
  • การทดสอบ: Intl polyfill สำหรับเบราว์เซอร์รุ่นเก่า

ปิด

การจัดการวันที่และตัวเลขให้ถูกต้องเป็นการลงทุนที่ใช้ความพยายามน้อยแต่ให้ผลกระทบสูง: เพิ่มความเชื่อถือ ลดข้อผิดพลาด และสร้างประสบการณ์ระดับโลกที่ราบรื่น การจัดรูปแบบให้เป็นศูนย์กลาง เก็บค่ามาตรฐาน ใช้ API ที่รับรู้ท้องถิ่นทุกที่ที่ผู้ใช้ของคุณอ่านหรือพิมพ์เวลา เงิน หรือเลข—และรู้ว่าเมื่อใดควรข้ามการแปลสำหรับข้อมูลที่เครื่องอ่านได้ ด้วยการแคชและการทดสอบที่เหมาะสม คุณจะสร้างระบบที่แข็งแกร่งซึ่งขยายได้ทั่วท้องถิ่นโดยไม่ลดทอนประสิทธิภาพ

Related Posts

แปลอีเมลธุรกิจอย่างมืออาชีพใน 3 ขั้นตอน

แปลอีเมลธุรกิจอย่างมืออาชีพใน 3 ขั้นตอน

เวิร์กโฟลว์ที่รวดเร็วและเชื่อถือได้สำหรับการแปลอีเมลธุรกิจด้วยโทนเสียงที่เหมาะสม การจัดรูปแบบ และขนบธรรมเนียมท้องถิ่น—รวมถึงหัวเรื่อง เทมเพลต และรายการตรวจสอบ QA ที่ใช้เวลาเพียง 30 วินาที

2025/10/14
วิธีแปลเอกสารทางเทคนิคโดยไม่ทำให้โค้ดเสียหาย

วิธีแปลเอกสารทางเทคนิคโดยไม่ทำให้โค้ดเสียหาย

เวิร์กโฟลว์ที่ใช้งานได้จริงสำหรับการแปลเอกสารนักพัฒนาโดยไม่ทำให้บล็อกโค้ด ลิงก์ แองเคอร์ หรือข้อมูลที่มีโครงสร้างเสียหาย—มาพร้อมกับแนวทางป้องกัน ตัวอย่าง และการตรวจสอบคุณภาพ (QA)

2025/10/13
10 เคล็ดลับเพื่อผลลัพธ์การแปลที่ดียิ่งขึ้นในปี 2025

10 เคล็ดลับเพื่อผลลัพธ์การแปลที่ดียิ่งขึ้นในปี 2025

กลยุทธ์เชิงปฏิบัติที่ไม่ยึดติดกับเครื่องมือเพื่อเพิ่มคุณภาพการแปลในเอกสาร เว็บไซต์ และมัลติมีเดีย - ขั้นตอนที่ชัดเจนที่คุณสามารถนำไปใช้ได้วันนี้

2025/9/23