# טיפול ב־locale *locale* הוא מערכת המוסכמות התרבותיות שתוכנית עוקבת אחריהן כשהיא ממיינת טקסט, מחליפה רישיות, מעצבת מספרים וכסף, נוקבת בשמות ימי השבוע, או כותבת הודעת שגיאה. אותו מערך מילים ממוין באופן אחד תחת locale שוודי ובאופן אחר תחת locale גרמני; המספר שתים־עשרה וחצי מודפס כ־`12.5` במדינה אחת וכ־`12,5` באחרת. טיפול ב־locale הוא האופן שבו Perl מאפשרת לתוכנית יחידה להסתגל למוסכמות הללו בזמן ריצה במקום לקבע בקוד את הכללים של מדינה אחת. כברירת מחדל PetaPerl מתעלמת מ־locale לחלוטין: כל פעולה מובנית מתנהגת באותו אופן ללא תלות בסביבת המשתמש, בעזרת מוסכמות C/POSIX (collation של ASCII, `.` כנקודה העשרונית, שמות חודשים באנגלית). מצטרפים למודעות ל־locale, תחום לקסיקלי אחד בכל פעם, באמצעות הפרגמה `use locale`. עמוד זה מכסה מה הפרגמה הזו מפעילה, אילו פעולות היא משפיעה עליהן, כיצד לקבוע ולבחון את ה־locale הפעיל, והיכן locale ו־Unicode מתממשקים. ## מהו locale ספריית ה־C של המערכת מחלקת את המוסכמות התרבותיות ל *קטגוריות* בלתי־תלויות, כל אחת בשם `LC_` ואחריו התחום שעליו היא חולשת. מיון (`LC_COLLATE`) נפרד מכללי רישיות (`LC_CTYPE`), שנפרדים מעיצוב מספרים (`LC_NUMERIC`), וכן הלאה. locale הוא צרור הגדרות בעל שם - `de_DE.UTF-8`, `sv_SE.UTF-8`, `C` - ומעבר אליו עשוי לשנות את כל הקטגוריות בבת אחת או רק את אלו שבחרת. הקטגוריות ש־PetaPerl מכבדת מפורטות בטבלת הקטגוריות שלהלן. ## הפרגמה `use locale` התנהגות רגישה ל־locale היא **כבויה כברירת מחדל** ו**מתוחמת לקסיקלית**. `use locale` מפעילה אותה מאותה נקודה ועד סוף הבלוק המקיף (או הקובץ); `no locale` מכבה אותה שוב עבור שארית התחום שלה. שום דבר מחוץ לתחום הלקסיקלי אינו מושפע - מודול שאינו מציין `use locale` שומר על התנהגות ברירת המחדל של C-locale גם כשהוא נקרא מקוד שכן ציין זאת. ```perl use locale; # locale-aware from here down my @sorted = sort @words; # collates per LC_COLLATE { no locale; # back to codepoint order in this block my @plain = sort @words; } ``` ללא הפרגמה, `sort`, `lc`, `uc`, `printf` והשאר משתמשים בכללי C-locale קבועים ללא קשר למה שהסביבה אומרת. זוהי ברירת מחדל בטיחותית מכוונת: תוכנית מפיקה את אותו פלט בכל מכונה עד שהיא מבקשת במפורש לעקוב אחר המוסכמות המקומיות. הפרגמה קובעת רמז ברמת הוראה, בדיוק כפי ש־Perl מהמעלה־הזרם עושה, כך שקובץ יחיד יכול לערבב חופשית אזורים מודעי locale ואזורים עיוורי locale. ההגדרה נעה עם התחום הלקסיקלי, לא עם מחסנית הקריאות. ## קטגוריות locale כל קטגוריה שולטת בקבוצה נבדלת של פעולות. `use locale` מפעילה את כולן בבת אחת; בוחרים *איזה* locale פעיל לכל קטגוריה דרך [`setlocale`](../POSIX/setlocale.md). עמודת ״הפעולות המושפעות״ מקשרת לעמודי הייחוס שבהם ההתנהגות מתועדת במלואה - שם נמצאים הכללים הספציפיים ל־locale של כל פעולה מובנית. | קטגוריה | חולשת על | פעולות מושפעות | |---------------|--------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------| | `LC_COLLATE` | סדר מיון והשוואה של מחרוזות | [`sort`](perlfunc/sort.md), השוואות המחרוזות [`lt` `le` `gt` `ge` `cmp`](perlop.md) | | `LC_CTYPE` | סיווג תווים ומיפוי רישיות | [`lc`](perlfunc/lc.md), [`uc`](perlfunc/uc.md), [`lcfirst`](perlfunc/lcfirst.md), [`ucfirst`](perlfunc/ucfirst.md), `\w` `\d` `\s` ו־`\b` ב־regex | | `LC_NUMERIC` | נקודה עשרונית וקיבוץ ספרות | [`printf`](perlfunc/printf.md), [`sprintf`](perlfunc/sprintf.md), [המרת מספר־למחרוזת](perldata/numeric-strings.md) | | `LC_MONETARY` | מוסכמות עיצוב מטבע | [`localeconv`](../POSIX/localeconv.md) (בחינה בלבד; אין פעולה מובנית שמעצבת כסף עבורך) | | `LC_TIME` | שמות ימים וחודשים, פריסת תאריך | `strftime` דרך [`POSIX`](../POSIX.md), [`langinfo`](../I18N/Langinfo.md) | | `LC_MESSAGES` | שפת מחרוזות שגיאת המערכת | טקסט [`$!`](perlvar/error.md), מחרוזות הודעה של [`langinfo`](../I18N/Langinfo.md) | `LC_ALL` אינו קטגוריה בפני עצמו אלא קיצור שקובע את כל הקטגוריות בבת אחת. שים לב לאי־סימטריה אחת שמכשילה אנשים: `LC_NUMERIC` משנה כיצד מספרים *מעוצבים לפלט*, אך קוד המקור של Perl עצמו וה *ניתוח* המספרי שלו תמיד משתמשים ב־`.` כמפריד העשרוני. סקריפט שקורא `12,5` מקובץ של locale גרמני עדיין צריך לתרגם את הפסיק עצמו לפני שיתייחס אליו כמספר - ה־locale אינו גורם ל־`"12,5" + 0` להניב `12.5`. ראה [מספרים ומחרוזות](perldata/numeric-strings.md). ## קביעת ה־locale `use locale` אומרת *עקוב אחר ה־locale*; היא אינה אומרת *איזה* locale. הבחירה הזו מגיעה מהסביבה כברירת מחדל, וניתן לתשאל אותה או לעקוף אותה דרך המודול `POSIX`. [`setlocale`](../POSIX/setlocale.md) בוחרת את ה־locale הפעיל עבור קטגוריה. הקריאה הניבית מכבדת את סביבת המשתמש (`LANG`, `LC_*`): ```perl use POSIX qw(setlocale LC_ALL LC_COLLATE); setlocale(LC_ALL, ""); # adopt the environment's locale my $cur = setlocale(LC_COLLATE); # query the active collation setlocale(LC_COLLATE, "sv_SE.UTF-8"); # force one explicitly ``` [`localeconv`](../POSIX/localeconv.md) מחזירה האש המתאר את מוסכמות ה־`LC_NUMERIC` וה־`LC_MONETARY` הפעילות - הנקודה העשרונית, מפריד האלפים, סמל המטבע, והשאר - כך שתוכנית יכולה לעצב ערכים בעצמה כשאין פעולה מובנית שעושה זאת ישירות. [`I18N::Langinfo`](../I18N/Langinfo.md) חושף את `langinfo`, הקורא פריטים בודדים מתוך ה־locale הנוכחי: השם המתורגם של יום בשבוע או חודש (`DAY_1`, `MON_1`), מחרוזת פורמט התאריך, תו הבסיס, סמל המטבע. זהו הבן־לוויה הצר, פריט־בכל־פעם, של `localeconv`. ## locale ו־Unicode טיפול ב־locale ו־Unicode הם שתי תשובות שונות ל״מהו תו״, והם מתממשקים בדרכים שכדאי להבין לפני שמשלבים ביניהם. הטיפול המלא - כיצד `use utf8`, שכבות קלט/פלט של UTF-8, וכללי `LC_CTYPE` של locale מתחברים, והמלכודות שצצות כשהם חלוקים - נמצא במדריך Unicode. התחל ב־[מחרוזות וקידודים ב־Unicode](../../tutorial/unicode/strings-and-encodings.md) וב־[פרק המלכודות](../../tutorial/unicode/pitfalls.md); [פרק regex והתכונות](../../tutorial/unicode/regex-and-properties.md) מכסה כיצד `\w` ומחלקות התווים מתנהגות תחת כל מודל. ## דליפות locale ובטיחות locale הוא מצב גלובלי־לתהליך בספריית ה־C שמתחת, ולכן קריאת `setlocale` שנעשית בכל מקום משנה את ה־locale בכל מקום בתהליך - חוצה גבולות מודולים, לא רק את התחום שקרא לה. נובעות מכך שתי השלכות: - **`use locale` בטוחה לתיחום; `setlocale` אינה.** הפרגמה לקסיקלית ואינה מדליפה דבר. קריאת `setlocale` היא תופעת לוואי גלובלית - אם ספרייה קובעת את `LC_NUMERIC` ל־locale עם פסיק עשרוני ושוכחת לשחזר אותו, כל `printf` מאוחר יותר בתוכנית מושפע. שמור ושחזר סביב שינוי זמני: ```perl my $saved = setlocale(LC_NUMERIC); setlocale(LC_NUMERIC, "de_DE.UTF-8"); # ... locale-sensitive work ... setlocale(LC_NUMERIC, $saved); ``` - **שמות locale לא מהימנים הם קלט לא מהימן.** העברת מחרוזת המסופקת מהסביבה ישירות ל־`setlocale` מאפשרת לסביבה לכוון את עיצוב התוכנית שלך. בהקשר רגיש מבחינת אבטחה, אמת את השם או קבע את ה־locale במפורש במקום לקרוא ל־`setlocale(LC_ALL, "")`. ## ביצוע מקבילי ו־locale PetaPerl ממקבלת אוטומטית חלק מהלולאות המספריות על פני worker threads. הדבר לעולם אינו משפיע על קוד רגיש ל־locale, מעצם הבנייה. פעולות שתוצאותיהן תלויות ב־locale הנוכחי - `sort` עם ה־collation המוגדר כברירת מחדל, השוואת מחרוזות `LC_COLLATE`, קיפול אותיות `lc`/`uc`/`fc`, ועיצוב מספרים `LC_NUMERIC` - לעולם אינן עוברות הידור JIT או מיקבול אוטומטי; הן תמיד מתבצעות באופן סדרתי בפרשן מול ה־locale היחיד כלל־התהליכי. מיקבול אוטומטי מריץ אך ורק גופי לולאה מספריים, ולכן שום חישוב רגיש ל־locale אינו מופנה על פני worker threads. אינך צריך להגן על מצב ה־locale בכתיבת קוד ניתן־למיקבול: הנתיב המקבילי פשוט לעולם אינו נוגע בו. ## משתני סביבה כשתוכנית קוראת ל־`setlocale(LC_ALL, "")`, ספריית ה־C קוראת את ה־locale מהסביבה בסדר עדיפות קבוע: `LC_ALL` עוקף כל משתנה `LC_*` בודד, כל משתנה `LC_*` קובע את הקטגוריה שלו, ו־`LANG` מספק את ברירת המחדל לכל קטגוריה שלא צוינה אחרת. משתנים אלו חיים ב־[`%ENV`](perlvar/args-env-inc.md) כמו כל ערך סביבה אחר, כך שתוכנית יכולה לבחון או להתאים אותם לפני קריאת `setlocale` שצורכת אותם. | משתנה | השפעה | |-----------------------------|---------------------------------------| | `LC_ALL` | עוקף את כל הקטגוריות | | `LC_COLLATE`, `LC_CTYPE`, … | קובע קטגוריה אחת בעלת שם | | `LANG` | ברירת מחדל לכל קטגוריה שלא נקבעה לעיל | ## הבדלים מן ה-upstream - **Linux בלבד, UTF-8 נייטיבי.** PetaPerl רצה רק על Linux מול ה־locales של ספריית ה־C של המערכת. מנגנון ה־locale הספציפי לפלטפורמה ש־Perl מהמעלה־הזרם נושאת עבור VMS, Windows ו־Android - מתאמי ה־locale של `Win32::`, מוזרויות הקטגוריות של VMS, חלופות ה״locales אינם זמינים בפלטפורמה זו״ - אין לו מקבילה כאן והוא פשוט נעדר. יש מודל locale אחד: זה של POSIX ש־`glibc` שלך מספק. - **`LC_NUMERIC` וניתוח מקור.** כמו במעלה־הזרם, המפריד העשרוני המשמש כש־Perl *מנתחת* ליטרלים מספריים והמרות מחרוזת־למספר הוא תמיד `.`, ללא תלות ב־locale; רק *עיצוב* הפלט מכבד את `LC_NUMERIC`. PetaPerl אינה עושה חריג לכך. - **מיקבול אוטומטי לעולם אינו נוגע בקוד רגיש ל־locale.** PetaPerl ממקבלת אוטומטית חלק מהלולאות המספריות על פני worker threads, יכולת ש־Perl מהמעלה־הזרם אינה מחזיקה. מכיוון שפעולות תלויות־locale (collation, קיפול אותיות, עיצוב מספרים) לעולם אינן עוברות הידור JIT או מיקבול, הן תמיד רצות באופן סדרתי מול ה־locale היחיד כלל־התהליכי - כך שהתכונה אינה מציגה כל חשש בטיחות locale משלה. ראה [ביצוע מקבילי ו־locale]() לעיל. ## ראו גם - [`perlfunc`](perlfunc.md) - הפעולות המובנות שה־locale משנה את התנהגותן: `sort`, `lc`, `uc`, `lcfirst`, `ucfirst`, `sprintf`, `printf`. - [`perlop`](perlop.md) - אופרטורי השוואת המחרוזות (`lt`, `cmp`, …) שמבצעים collation תחת `LC_COLLATE`. - [`perlvar`](perlvar.md) - `%ENV` מחזיק את המשתנים `LANG`/`LC_*`; `$!` נושא טקסט שגיאה מתורגם ל־locale. - [`POSIX`](../POSIX.md) - `setlocale` ו־`localeconv`, הממשק לבחירה ולבחינה של ה־locale הפעיל. - [`I18N::Langinfo`](../I18N/Langinfo.md) - `langinfo`, לקריאת פריט מתורגם אחד (שם חודש, תו בסיס) בכל פעם. - [מחרוזות וקידודים ב־Unicode](../../tutorial/unicode/strings-and-encodings.md) - כיצד מודל התווים של Unicode מתייחס ל־`LC_CTYPE` של locale.