Locale هي كلاس Foundation في iOS وmacOS تغلف الاتفاقيات اللغوية والثقافية للمستخدم: تنسيق التواريخ والأرقام والعملات ووحدات القياس. وفقًا لـ Apple Developer Documentation, 2024، Locale تحدد كيف يعرض DateFormatter الشهر (يناير أو January)، وفاصل الأعشار في الرقم (فاصلة أو نقطة) ورمز العملة (روبل أو دولار أو يورو). كل مثيل Locale مرتبط بمعرف مثل ru_RU أو en_US، حيث الجزء الأول هو رمز اللغة (ISO 639-1) والثاني هو رمز المنطقة (ISO 3166-1). على عكس TimeZone، لا تؤثر Locale على القيمة المطلقة للوقت، فقط على تمثيلها النصي.
النقاط الرئيسية
Locale هو نوع قيمة في Swift (NSLocale في Objective-C) يمثل مجموعة من قواعد التنسيق الخاصة بلغة ومنطقة معينة. على عكس TimeZone الذي يحدد الإزاحة المطلقة للوقت، تحدد Locale كيف يبدو الوقت والأرقام والعملة في التمثيل النصي. نفس التاريخ 2024-07-21 سيظهر كـ «21 يوليو 2024» لـ ru_RU و«July 21, 2024» لـ en_US.
كل مثيل Locale يتكون من مكونين: اللغة (تحدد أسماء الأشهر وأيام الأسبوع وترتيب الكلمات) والمنطقة (تحدد تنسيق الأرقام والعملة والتقويم). يتم ترميز مجموعة هذه المكونات في معرف وفقًا لمعيار BCP 47: ru_RU (الروسية، روسيا)، en_US (الإنجليزية، الولايات المتحدة)، de_DE (الألمانية، ألمانيا).
وفقًا لـ Unicode CLDR (2024)، فإن عدد الإعدادات الإقليمية المدعومة في iOS يتجاوز 700 مجموعة لغة-منطقة. يستخدم Foundation بيانات من CLDR (مستودع بيانات الإعدادات الإقليمية المشتركة) — أكثر مستودعات بيانات التوطين اكتمالاً التي يحتفظ بها Unicode Consortium. وهذا يضمن تنسيقًا متسقًا عبر جميع أجهزة Apple.
DateFormatter يستخدم Locale لاختيار أسماء الأشهر والأيام الصحيحة، وتحديد ترتيب مكونات التاريخ (يوم/شهر/سنة أو شهر/يوم/سنة) والفواصل. بدون تحديد Locale بشكل صريح، يستخدم DateFormatter الإعدادات الإقليمية للجهاز — هذا صحيح لواجهة المستخدم ولكنه خطير لبيانات الخادم حيث يجب أن يكون التنسيق ثابتًا.
| المكون | ru_RU | en_US | de_DE |
|---|---|---|---|
| التاريخ (medium) | 21 يوليو 2024 | Jul 21, 2024 | 21.07.2024 |
| الرقم (1000.5) | 1 000,5 | 1,000.5 | 1.000,5 |
| العملة (100) | 100,00 ₽ | $100.00 | 100,00 € |
| التقويم | ميلادي | ميلادي | ميلادي |
| فاصل القائمة | ; | , | ; |
NumberFormatter يستخدم Locale لتحديد الفاصل العشري (فاصلة أو نقطة)، وفاصل التجميع (مسافة، فاصلة، نقطة) ورمز العملة. تجاهل Locale عند تحليل الأرقام هو أحد الأسباب الشائعة للأخطاء في التطبيقات الدولية: الرقم «1,5» يعني «واحد ونصف» لـ ru_RU، ولكن لـ en_US سيقرأه المحلل الرقمي كـ «خمسة» بعد الفاصلة.
مهم: Calendar الذي تم إنشاؤه عبر Calendar.current يرث الإعدادات الإقليمية للجهاز. Calendar(identifier: .gregorian) مع إعدادات إقليمية محددة بشكل صريح هو الأسلوب الموصى به للتنسيق القابل للتنبؤ. عند العمل مع تواريخ ISO 8601، استخدم دائمًا Locale(identifier: «en_US_POSIX») — إعدادات إقليمية خاصة للتنسيق التقني غير المتأثر بالإعدادات الإقليمية.
معرف Locale يتكون من رمز اللغة (ISO 639-1، حرفان) ورمز المنطقة (ISO 3166-1، حرفان)، مفصولين بشرطة سفلية. أمثلة: ru_RU، en_US، fr_FR، zh_Hans_CN (صينية، كتابة مبسطة، الصين). Foundation يدعم أيضًا المعرفات بتنسيق BCP 47: ru-RU، en-US، المستخدمة في معايير الويب.
بالإضافة إلى المعرفات الكاملة، يمكن إنشاء Locale باللغة فقط: Locale(identifier: «ru») يعيد إعدادات إقليمية باللغة الروسية والمنطقة الافتراضية لتلك اللغة (عادة روسيا). وبالمثل للإنجليزية: Locale(identifier: «en») يستخدم منطقة الولايات المتحدة. هذا الأسلوب مفيد لتعيين لغة التنسيق دون الارتباط بمنطقة محددة.
الإعدادات الإقليمية الخاصة تشمل en_US_POSIX — إعدادات إقليمية تقنية للتنسيق الآلي للتواريخ والأرقام، تضمن تنسيقًا ثابتًا بغض النظر عن إعدادات المستخدم. هذه الإعدادات الإقليمية إلزامية لتحليل التواريخ من واجهات برمجة تطبيقات الخادم، خاصة لتنسيق ISO 8601. تستخدم التقويم الميلادي، تنسيق الوقت 24 ساعة والنقطة كفاصل عشري.
import Foundation
// معرفات الإعدادات الإقليمية المتاحة
let available: [String] = Locale.availableIdentifiers
print("إجمالي الإعدادات الإقليمية: \(available.count)")
// تصفية الإعدادات الإقليمية الروسية
let russianLocales = available.filter { $0.hasPrefix("ru") }
print("الإعدادات الإقليمية الروسية: \(russianLocales)")
// مكونات الإعدادات الإقليمية
let locale = Locale(identifier: "de_DE")
print("اللغة: \(locale.languageCode ?? "nil")")
print("المنطقة: \(locale.regionCode ?? "nil")")
print("العملة: \(locale.currencyCode ?? "nil")")
print("التقويم: \(locale.calendar.identifier)")
التحقق من الإعدادات الإقليمية المتاحة عبر Locale.availableIdentifiers يعيد مصفوفة من جميع المعرفات المدعومة من قبل إصدار iOS الحالي. للتصفية حسب المنطقة، استخدم Locale.availableIdentifiers.filter مع التحقق من regionCode. هذا مفيد لبناء واجهة مستخدم لاختيار المنطقة بدون قائمة مشفرة.
Locale.current هو الطريقة الرئيسية للحصول على الإعدادات الإقليمية الحالية للجهاز التي يحددها المستخدم في إعدادات iOS (Settings > General > Language & Region). يتم تحديث هذه الخاصية تلقائيًا عند تغيير اللغة أو المنطقة في الإعدادات دون إعادة تشغيل التطبيق. ومع ذلك، قد لا تتطابق مع الإعدادات الإقليمية المفضلة لعرض المحتوى: يمكن للمستخدم تعيين لغة الواجهة إلى الإنجليزية ولكن عرض التواريخ بالتنسيق الروسي.
لتحديد أكثر دقة لتفضيلات المستخدم، استخدم Locale.preferredLanguages — مصفوفة من اللغات مرتبة حسب أولوية المستخدم. العنصر الأول هو لغة الواجهة الأساسية. تتوافق هذه القائمة مع الإعدادات في Language & Region، بما في ذلك سحب اللغات بترتيب التفضيل. يجب على تطبيقات الاتصال (المراسلات، عملاء البريد الإلكتروني) مراعاة هذا الترتيب عند اختيار لغة عرض المحتوى.
import Foundation
// الإعدادات الإقليمية الحالية للنظام
let current = Locale.current
print("الإعدادات الإقليمية الحالية: \(current.identifier)")
print("اللغة: \(current.language?.disjointName ?? "nil")")
// اللغات المفضلة للمستخدم
let preferred = Locale.preferredLanguages
print("اللغات المفضلة: \(preferred)")
// الحصول على المنطقة من الإعدادات الإقليمية الحالية
if let region = current.regionCode {
let regionLocale = Locale(identifier: "en_\(region)")
let countryName = regionLocale.localizedString(
forRegionCode: region
)
print("البلد: \(countryName ?? region)")
}
// التحقق من تنسيق 24 ساعة
let uses24h = current.uses24hClock(
for: .dateAndTime
)
print("يستخدم 24 ساعة: \(uses24h)")
التوطين في واجهة المستخدم: لعرض أسماء الأشهر والأيام بلغة الواجهة، استخدم Calendar مع إعدادات إقليمية محددة. Calendar.current.symbols(for: .month) يعيد أسماء الأشهر بلغة الإعدادات الإقليمية الحالية. لعرض أسماء الدول بلغة المستخدم، استخدم Locale.current.localizedString(forRegionCode:).
تنسيق التاريخ مع مراعاة الإعدادات الإقليمية هو مهمة رئيسية عند عرض التواريخ للمستخدم. DateFormatter مع إعدادات إقليمية محددة يختار تلقائيًا تنسيق التاريخ والوقت الصحيح لمنطقة المستخدم. بالنسبة لـ dateStyle وtimeStyle بقيم .short، .medium، .long، .full، يستخدم المنسق قواعد الإعدادات الإقليمية لتكوين مكونات التاريخ.
import Foundation
let date = Date()
// التنسيق بإعدادات إقليمية مختلفة
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.locale = Locale(identifier: "ru_RU")
print("الروسية: \(formatter.string(from: date))")
formatter.locale = Locale(identifier: "en_US")
print("الإنجليزية: \(formatter.string(from: date))")
formatter.locale = Locale(identifier: "ja_JP")
print("اليابانية: \(formatter.string(from: date))")
// تنسيق العملة مع الإعدادات الإقليمية
let numFormatter = NumberFormatter()
numFormatter.numberStyle = .currency
numFormatter.locale = Locale(identifier: "de_DE")
print("العملة الألمانية: \(numFormatter.string(from: 1234.56) ?? "nil")")
numFormatter.locale = Locale(identifier: "en_US")
print("العملة الأمريكية: \(numFormatter.string(from: 1234.56) ?? "nil")")
تحليل التواريخ من واجهات برمجة تطبيقات الخادم يجب أن يستخدم دائمًا Locale(identifier: «en_US_POSIX») لتنسيق ثابت. ترسل الخوادم عادة التواريخ بتنسيق ISO 8601 مع أسماء الأشهر بالإنجليزية، واستخدام الإعدادات الإقليمية الحالية للجهاز قد يسبب أخطاء في التحليل إذا كان المستخدم في منطقة غير ناطقة بالإنجليزية. يضمن en_US_POSIX أن التحليل لا يعتمد على إعدادات الجهاز.
import Foundation
// تحليل صحيح لتاريخ الخادم
let isoFormatter = DateFormatter()
isoFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
isoFormatter.locale = Locale(identifier: "en_US_POSIX")
isoFormatter.timeZone = TimeZone(secondsFromGMT: 0)
let serverDate = "2024-07-21T14:30:00+0000"
if let parsed = isoFormatter.date(from: serverDate) {
print("التاريخ المحلل: \(parsed)")
}
// اسم العملة المحلي
let usLocale = Locale(identifier: "en_US")
let currencyName = usLocale.localizedString(
forCurrencyCode: "RUB"
)
print("الروبل الروسي في الإعدادات الإقليمية الأمريكية: \(currencyName ?? "nil")")
إمكانيات إضافية: توفر Locale أوصافًا محلية لمكوناتها من خلال الطرق localizedString(forRegionCode:)، localizedString(forLanguageCode:)، localizedString(forCurrencyCode:) وlocalizedString(forCalendarIdentifier:). تعيد هذه الطرق الأسماء بلغة الإعدادات الإقليمية التي تم استدعاؤها عليها. على سبيل المثال، Locale(identifier: «ru_RU»).localizedString(forCountryCode: «DE») يعيد «ألمانيا».
تجاهل Locale عند تحليل الأرقام هو خطأ خطير في التطبيقات الدولية. NumberFormatter بدون إعدادات إقليمية صريحة يستخدم الإعدادات الإقليمية الحالية للجهاز. إذا أدخل مستخدم في روسيا «1,5»، فإن NumberFormatter.number(from: «1,5») يعيد بشكل صحيح 1.5. ولكن إذا تم تشغيل نفس الكود على جهاز بإعدادات إقليمية en_US، فإن التحليل يعيد nil لأن الفاصل العشري لـ en_US هو نقطة.
عدم استخدام en_US_POSIX لتواريخ الخادم يؤدي إلى أخطاء يصعب اكتشافها. DateFormatter مع dateFormat و locale = Locale.current قد يفشل لدى المستخدمين من المناطق التي يختلف فيها تنسيق التاريخ عن التنسيق الأمريكي. على سبيل المثال، في ألمانيا قد يتوقع DateFormatter «21.07.2024» بينما يرسل الخادم «07/21/2024». يضمن en_US_POSIX تنسيقًا ثابتًا للتحليل الآلي بغض النظر عن منطقة المستخدم.
مقارنة سلاسل التواريخ بدلاً من استخدام Date هو خطأ شائع آخر. يقارن المطورون أحيانًا تمثيلات نصية للتواريخ من إعدادات إقليمية مختلفة، مما يعطي نتائج غير صحيحة. Locale يغير فقط العرض، وليس القيمة المطلقة للتاريخ. قارن دائمًا كائنات Date، وليس تمثيلاتها النصية. لمقارنة مكونات التاريخ، استخدم Calendar مع إعدادات إقليمية محددة بشكل صريح.
وفقًا لـ WWDC 2023، حوالي 30% من مشاكل التدويل في التطبيقات مرتبطة بتكوين Locale غير صحيح. توصي Apple دائمًا بتعيين الإعدادات الإقليمية بشكل صريح لـ DateFormatter وNumberFormatter عند العمل مع بيانات الخادم واستخدام Locale.current فقط لعرض واجهة المستخدم. هذه الممارسة البسيطة تقضي على معظم الأخطاء المتعلقة بالإعدادات الإقليمية.
الأسئلة الشائعة
Locale هي كلاس Foundation تمثل قواعد التنسيق الثقافية واللغوية: تنسيق التاريخ والرقم والعملة ووحدات القياس. تستخدم مع DateFormatter وNumberFormatter وCalendar لعرض البيانات بشكل محلي.
Locale تحدد تنسيق العرض (اللغة، الاتفاقيات الإقليمية)، بينما TimeZone تحدد الإزاحة المطلقة للوقت بالنسبة لـ UTC. Locale تؤثر على التمثيل النصي، TimeZone تؤثر على القيمة الرقمية للوقت. يستخدم كلاهما معًا للتنسيق الكامل للتاريخ.
en_US_POSIX هي إعدادات إقليمية خاصة للتنسيق التقني تضمن تنسيقًا ثابتًا بغض النظر عن إعدادات المستخدم. وهي إلزامية لتحليل تواريخ الخادم (ISO 8601) والعمل مع واجهات برمجة التطبيقات حيث يجب أن يكون التنسيق قابلاً للتنبؤ.
Locale.availableIdentifiers يعيد مصفوفة من السلاسل مع معرفات جميع الإعدادات الإقليمية المدعومة. للتصفية حسب اللغة، استخدم filter مع hasPrefix؛ للحصول على المنطقة، استخدم Locale(identifier:).regionCode.
NumberFormatter يستخدم Locale لتحديد الفاصل العشري (فاصلة أو نقطة)، رمز العملة وفاصل التجميع. لتنسيق ثابت، قم بتعيين الإعدادات الإقليمية إلى en_US_POSIX أو قم بتعيين خصائص المنسق بشكل صريح.
الملخص
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.
اقرأ أيضًا