-
Notifications
You must be signed in to change notification settings - Fork 0
Tutorial 5 Localization kn
ಗುರಿ: LockedIn CLI ಹೇಗೆ 33 ಭಾಷೆಗಳಲ್ಲಿ ಮಾತನಾಡುತ್ತದೆ ಎಂಬುದನ್ನು ಅರ್ಥಮಾಡಿಕೊಳ್ಳಿ — ಮತ್ತು ಒಂದು ಏಜೆಂಟ್ಗೆ ಇನ್ನೊಂದು ಭಾಷೆ ಸೇರಿಸಲು ನಿರ್ದೇಶಿಸುವುದನ್ನು ಅಭ್ಯಾಸ ಮಾಡಿ. ಲೋಕಲೈಸೇಶನ್ ಒಂದು ಅದ್ಭುತ ಏಜೆಂಟ್ ಟಾಸ್ಕ್: ಇದು delegate ಮಾಡಲು ಸಾಕಷ್ಟು ಯಾಂತ್ರಿಕ, ಆದರೆ ಇದಕ್ಕೆ ನಿಜವಾದ constraint ಗಳಿವೆ (ಒಂದು test ಗೇಟ್, layout ನಿಯಮಗಳು, ವ್ಯಾಕರಣ review) ಇವು ನಿಮಗೆ review ಮಾಡುವುದನ್ನು ಕಲಿಸುತ್ತವೆ.
← ಹಿಂದಿನದು: ಟ್ಯುಟೋರಿಯಲ್ 4 ಪ್ರಾಂಪ್ಟಿಂಗ್ ಮತ್ತು ರಿವ್ಯೂ · ಮುಖಪುಟ ಗೆ ಹಿಂತಿರುಗಿ
CLI ಅನ್ನು ಸ್ಪ್ಯಾನಿಷ್, ಹಿಂದಿ, ಜಪಾನೀಸ್, ಸರಳೀಕೃತ ಚೀನೀ, ಅಥವಾ ಯಾವುದೇ shipped ಭಾಷೆಯಲ್ಲಿ ಚಲಾಯಿಸಿ ಮತ್ತು ಎಲ್ಲವೂ ಬದಲಾಗುತ್ತದೆ — splash, help table, ಪ್ರತಿ ಕಮಾಂಡ್ನ output, chat session, ಕಡೆಗೆ legal fine print ಕೂಡ. ಕೇವಲ ತಮಾಷೆಗಳಲ್ಲ: ಇಡೀ ಗೋಚರ ಮೇಲ್ಮೈ.
lockedin --lang kn post
LOCKEDIN_LANG=hi lockedin
lockedin --lang zh auraಭಾಷೆ startup ನಲ್ಲಿ autodetect ಆಗುತ್ತದೆ, ಆದ್ಯತೆ ಕ್ರಮದಲ್ಲಿ ಪರಿಹರಿಸಲಾಗುತ್ತದೆ:
-
--langflag (--lang kn,--lang=fr,-l ja) -
LOCKEDIN_LANGenvironment variable - ನಿಮ್ಮ locale (
LC_ALL/LC_MESSAGES/LANG, ನಂತರ OS/runtime locale) - ಇಂಗ್ಲಿಷ್, fallback ಆಗಿ
normalizeLang() ಸಾಮಾನ್ಯವಾಗಿ locale ನ primary subtag ಬಳಸುತ್ತದೆ. ಅಂದರೆ de-DE de
ಆಯ್ಕೆ ಮಾಡುತ್ತದೆ, ಆದರೆ tlh ಆಕಸ್ಮಿಕವಾಗಿ tl ಆಗುವುದಿಲ್ಲ; ನಿಜವಾದ alias ಗಳಾದ fil
ಮತ್ತು tgl ಉದ್ದೇಶಪೂರ್ವಕವಾಗಿ Tagalog (tl) ಗೆ map ಆಗುತ್ತವೆ, ನಾರ್ವೇಜಿಯನ್ nb ಮತ್ತು
nn no ಗೆ map ಆಗುತ್ತವೆ, legacy Indonesian in id ಗೆ map ಆಗುತ್ತದೆ, ಮತ್ತು legacy
Hebrew iw he ಗೆ map ಆಗುತ್ತದೆ. ಎರಡು regional code ಗಳು ತಮ್ಮ primary subtag ಗೆ
ಮಡಚದೆ ಯಥಾವತ್ ಸಂರಕ್ಷಿಸಲ್ಪಡುತ್ತವೆ: pt-BR/pt_BR canonical regional code ಆಯ್ಕೆ
ಮಾಡುತ್ತವೆ, ಆದರೆ generic pt backward-compatible Brazilian Portuguese bundle ಆಗಿ
ಉಳಿಯುತ್ತದೆ (ಎರಡೂ Brazilian Portuguese ಮತ್ತು ಒಂದೇ pools/UI ಅನ್ನು ಹಂಚಿಕೊಳ್ಳುತ್ತವೆ),
ಮತ್ತು en-SG/en_SG Singlish ಇಡುತ್ತವೆ (generic en ಇಂಗ್ಲಿಷ್ ಆಗಿ ಉಳಿಯುತ್ತದೆ). Hong
Kong Traditional Chinese ಅದೇ ಬಗೆಯ ಅಪವಾದ: zh-HK, zh_HK.UTF-8, ಮತ್ತು zh-Hant-HK
zh-HK ಆಯ್ಕೆ ಮಾಡುತ್ತವೆ, ಆದರೆ generic zh ಮತ್ತು mainland tag ಗಳು ಸರಳೀಕೃತ ಚೀನೀ (zh)
ಆಯ್ಕೆ ಮಾಡುತ್ತವೆ.
ಮಧ್ಯದಲ್ಲಿ switch — /language panel. CLI ಯಾವಾಗಲೂ ಇನ್ನೊಂದು ಭಾಷೆಯಲ್ಲಿ ಆರಂಭಿಸಬಹುದಿತ್ತು
(--lang, LOCKEDIN_LANG); ಈಗ ನೀವು session ಮಧ್ಯದಲ್ಲಿ switch ಮಾಡಬಹುದು. /language
ಟೈಪ್ ಮಾಡಿ (alias /lang ಮತ್ತು /languages) ಎಲ್ಲಾ 33 ಭಾಷೆಗಳನ್ನು code ಪ್ರಕಾರ ಪಟ್ಟಿ
ಮಾಡಲು, ಪ್ರತಿಯೊಂದೂ ತನ್ನದೇ script ನಲ್ಲಿ; /language el ಉಳಿದ session ಗಾಗಿ switch ಮಾಡುತ್ತದೆ.
ಮುಖ್ಯ ಅಂಶ escape hatch: switch ನಂತರ ಇದು ಹೊಸ ಭಾಷೆಯಲ್ಲಿ ಮತ್ತೆ draw ಮಾಡುತ್ತದೆ ಮತ್ತು ನಂತರ,
ನೀವು ಈಗಷ್ಟೇ ಬಿಟ್ಟ ಭಾಷೆಯಲ್ಲಿ, ನಿಖರ ಹಿಂತಿರುಗುವ ದಾರಿಯನ್ನು print ಮಾಡುತ್ತದೆ — ಈಗ
/language en, ಮುಂದಿನ ಬಾರಿ lockedin --lang en — ಇದರಿಂದ ಆಕಸ್ಮಿಕವಾಗಿ 日本語 ಅಥವಾ
ಕನ್ನಡ ಗೆ ಬಿದ್ದರೂ ನೀವು ಎಂದಿಗೂ ಸಿಕ್ಕಿಹಾಕಿಕೊಳ್ಳುವುದಿಲ್ಲ. (ಎರಡು ಬಾರಿ switch ಮಾಡಿ ಮತ್ತು
ನಿಮ್ಮ LOCKEDIN_LANG ಹೆಸರಿಸುವ ಭಾಷೆಯನ್ನೂ ನೀಡಲಾಗುತ್ತದೆ.) --lang ಮತ್ತು LOCKEDIN_LANG
ಬದಲಾಗಿಲ್ಲ. /a11y ನಂತೆ, ಇದು ಒಂದು ಪ್ರಾಮಾಣಿಕ utility, satire ನ ಭಾಗವಲ್ಲ.
ಎಲ್ಲಾ translatable text bundle ಗಳಲ್ಲಿ ವಾಸಿಸುತ್ತದೆ, ಪ್ರತಿ ಭಾಷೆಗೆ ಒಂದು, ಪ್ರತಿಯೊಂದೂ ಈ ಆಕಾರದಲ್ಲಿ:
{ meta: { lang: 'kn', name: 'ಕನ್ನಡ', dir: 'ltr' },
pools: { HOOKS: [ /* ~25 */ ], LESSONS: [ /* ... */ ], /* ... */ },
ui: { buzzwordDensity: 'Buzzword ಸಾಂದ್ರತೆ: ', /* labels, headings */ } }-
poolsಎಂಬುದು ಅಧ್ಯಾಯ 2 ರಲ್ಲಿ ನೀವು ಭೇಟಿಯಾದ content array ಗಳು (ತಮಾಷೆಗಳು). -
uiಎಂಬುದು chrome string ಗಳು: label ಗಳು, heading ಗಳು, ಮತ್ತು ಚಿಕ್ಕ template ಗಳು.
ಇಂಗ್ಲಿಷ್ src/lockedin.js ಒಳಗಿನ reference bundle; ಉಳಿದ 32 bundle module ಗಳು
src/content/*.js ನಲ್ಲಿ ವಾಸಿಸುತ್ತವೆ: ar, bn, bo, de, el, en-SG, es,
eu, fa, fi, fr, he, hi, id, is, it, ja, kn, ms, nl, no,
pl, pt, pt-BR, ru, sv, tl, tr, uk, ur, zh, ಮತ್ತು zh-HK (pt-BR
pt ನ pools/UI ಅನ್ನು ಮರುಬಳಕೆ ಮಾಡುತ್ತದೆ ಆದರೆ ಪ್ರತ್ಯೇಕವಾಗಿ register ಆಗುತ್ತದೆ).
ಪ್ರತಿಯೊಂದೂ BUNDLES ನಲ್ಲಿ register ಆಗಿದೆ; SUPPORTED_LANGS ಆ key ಗಳಿಂದ ಉತ್ಪತ್ತಿಯಾಗುತ್ತದೆ,
ಮತ್ತು renderHelp() ಆ ಉತ್ಪತ್ತಿಯಾದ code ಪಟ್ಟಿಯನ್ನು print ಮಾಡುತ್ತದೆ. ಯಾವುದೇ UI bundle
ಪಟ್ಟಿಯನ್ನು hard-code ಮಾಡುವುದಿಲ್ಲ.
setLang('fr'); // active ಭಾಷೆಯನ್ನು French bundle ಗೆ ತೋರಿಸಿ
// L = ಸಕ್ರಿಯ pools, U = ಸಕ್ರಿಯ ui
pick(L.HOOKS) // ಒಂದು French hook
U.buzzwordDensity // "Densité de jargon : "ಪ್ರತಿ renderer L ಮತ್ತು U ಓದುವುದರಿಂದ (ಎಂದಿಗೂ hardcode ಆದ string ಅಲ್ಲ), ಕೇವಲ
setLang ಇಡೀ ಅನುಭವವನ್ನು ಬದಲಾಯಿಸುತ್ತದೆ. ಅದೇ ಇಡೀ ತಂತ್ರ.
ಒಂದು ಭಾಷೆ ಸೇರಿಸುವುದನ್ನು ಸುರಕ್ಷಿತ ಮಾಡುವ invariant ಇದು:
ಪ್ರತಿ bundle ಇಂಗ್ಲಿಷ್ನ ಅದೇ ನಿಖರ
poolsಮತ್ತುuikey ಗಳನ್ನು expose ಮಾಡಬೇಕು.
ಒಂದು test ಇದನ್ನು ಎಲ್ಲಾ 33 bundle ಗಳ ಉದ್ದಕ್ಕೂ ಜಾರಿಗೊಳಿಸುತ್ತದೆ. ನೀವು ಇಂಗ್ಲಿಷ್ನಲ್ಲಿ ಒಂದು
ಹೊಸ UI string ಸೇರಿಸಿ ಉಕ್ರೇನಿಯನ್ನಲ್ಲಿ ಅನುವಾದಿಸಲು ಮರೆತರೆ, npm test ಕೆಂಪಾಗುತ್ತದೆ ಮತ್ತು
ಯಾವ key ಇಲ್ಲ ಎಂದು ಹೇಳುತ್ತದೆ. ನೀವು ಮೌನವಾಗಿ ಅರ್ಧ-ಅನುವಾದಿತ ಭಾಷೆಯನ್ನು ship ಮಾಡಲಾಗದು.
ಭಾಷೆಗಳು terminal layout ಅನ್ನು ವಿವಿಧ ರೀತಿಯಲ್ಲಿ ಒತ್ತಡಕ್ಕೊಳಪಡಿಸುತ್ತವೆ:
-
ಜಪಾನೀಸ್, ಸರಳೀಕೃತ ಚೀನೀ, ಮತ್ತು Hong Kong Traditional Chinese East Asian Wide /
Fullwidth character ಗಳನ್ನು ಬಳಸುತ್ತವೆ.
vw()ಅವನ್ನು ಎರಡು column ಎಂದು ಎಣಿಸುತ್ತದೆ, ಮತ್ತುwrap()ಉದ್ದವಾದ space-ಇಲ್ಲದ token ಗಳನ್ನು hard-break ಮಾಡುತ್ತದೆ ಇದರಿಂದ CJK text card ಮತ್ತು box ಒಳಗೆ ಉಳಿಯುತ್ತದೆ. -
ಹಿಂದಿ ಮತ್ತು ಕನ್ನಡ nonspacing/enclosing combining mark (
Mn/Me) ಗಳನ್ನು ಬಳಸುತ್ತವೆ, ಉದಾಹರಣೆಗೆ ಮಾತ್ರಾ ಮತ್ತು ವಿರಾಮ.vw()ಅವನ್ನು ಶೂನ್ಯ column ಎಂದು ಎಣಿಸುತ್ತದೆ ಇದರಿಂದ ಅವು ಅಳೆದ width ಅನ್ನು ಉಬ್ಬಿಸುವುದಿಲ್ಲ. -
box()ಪ್ರತಿ body line ಅನ್ನು pad ಮಾಡುವ ಮೊದಲು wrap ಮಾಡುತ್ತದೆ, ಇದರಿಂದ ಉದ್ದವಾದ ಅನುವಾದಿತ banner ಇನ್ನು border ಅನ್ನು ತೂರಲಾಗದು. - ಪ್ರತಿ bundle
sentenceEndಮತ್ತುlistSepಅನ್ನು ಸೆಟ್ ಮಾಡುತ್ತದೆ (ಉದಾಹರಣೆಗೆ./。,,/、) ಇದರಿಂದ generator-ರಚಿತ ವಾಕ್ಯಗಳು ಸಹಜವಾಗಿ ಓದುತ್ತವೆ.
ನೀವು ಒಂದು ಭಾಷೆ ಸೇರಿಸಿದಾಗ, card header string ಗಳು (cardSubtitle, cardMeta,
cardFooter) ಇನ್ನೂ ≤ 60 visible column ಗಳಲ್ಲಿ ಹೊಂದಬೇಕು. ಅರೇಬಿಕ್, ಪರ್ಷಿಯನ್,
ಹೀಬ್ರೂ, ಮತ್ತು ಉರ್ದು meta.dir: 'rtl' ಅನ್ನು ಸೆಟ್ ಮಾಡುತ್ತವೆ. Output ನಲ್ಲಿ default ಆಗಿ
ಯಾವುದೇ bidi control ಇಲ್ಲ, ಏಕೆಂದರೆ ಕೆಲವು terminal ಅವನ್ನು boxed label ಆಗಿ render
ಮಾಡುತ್ತವೆ. LOCKEDIN_BIDI=on wrapping ನಂತರ balanced isolate ಗಳನ್ನು ಸ್ಪಷ್ಟವಾಗಿ ಸಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ
ಅವನ್ನು support ಮಾಡುವುದೆಂದು ತಿಳಿದ terminal ಗಳಿಗಾಗಿ, ANSI, ASCII command, ಮತ್ತು logical
copy/paste ಕ್ರಮವನ್ನು ಸಂರಕ್ಷಿಸುತ್ತಾ. Accessible output ಯಾವಾಗಲೂ ಆ control ಗಳನ್ನು ತೆಗೆದುಹಾಕುತ್ತದೆ.
opt-in ಇಲ್ಲದೆ, ಮಿಶ್ರ RTL/LTR ಕ್ರಮ ಕಡಿಮೆ ಪರಿಷ್ಕೃತವಾಗಿರಬಹುದು; ಎಂದಿಗೂ support ಅನ್ನು probe
ಅಥವಾ infer ಮಾಡಬೇಡಿ.
ಕೆಲವು UI template ಗಳು {cap} ನಂತಹ placeholder ಗಳೊಂದಿಗೆ raw user clause ಗಳನ್ನು splice
ಮಾಡುತ್ತವೆ. ಅವನ್ನು slot-for-slot ಅನುವಾದಿಸಬೇಡಿ. placeholder ಬಳಕೆದಾರ type ಮಾಡಿದ phrase
ಆಗಿದ್ದಾಗ, ಒಪ್ಪವಾದ noun ಅಲ್ಲದಿದ್ದಾಗಲೂ ವಾಕ್ಯ ವ್ಯಾಕರಣಸಮ್ಮತವಾಗಿ ಉಳಿಯಬೇಕು.
ಒಂದು ನಿಜವಾದ ಎಚ್ಚರಿಕೆಯ bug: {cap} ನ ನೇರ ನಂತರ は ಇಡುವ ಜಪಾನೀಸ್ template ಗಳು {cap}
ಒಂದು ಪೂರ್ಣ clause ಆಗಿದ್ದಾಗ ತಪ್ಪಾಗಿ ಕೇಳಿಸಬಹುದು. ಪರಿಹಾರ "ಹೆಚ್ಚು ಕಷ್ಟಪಟ್ಟು ಅನುವಾದಿಸು" ಅಲ್ಲ;
ಅದು template ಅನ್ನು ಪುನಾರಚಿಸುವುದು (ಉದಾಹರಣೆಗೆ, ಒಂದು nominalizer ಸೇರಿಸುವುದು ಅಥವಾ
placeholder ಚಲಿಸುವುದು) ಇದರಿಂದ ಯಾವುದೇ ಬಳಕೆದಾರ input ಇನ್ನೂ ಹೊಂದುತ್ತದೆ.
ಈ ಅಭ್ಯಾಸ ಇನ್ನೂ ಸರಿಯಾಗಿ ಅದೇ ರೀತಿ ಕೆಲಸ ಮಾಡುತ್ತದೆ. ನೀವು sanity-check ಮಾಡಬಹುದಾದ ಒಂದು ಭಾಷೆ ಆಯ್ಕೆ ಮಾಡಿ (ಅಥವಾ ಏಜೆಂಟ್ಗೆ ಮಾಡಲು ಹೇಳಿ), ಮತ್ತು ಅದನ್ನು ಆದ್ಯಂತವಾಗಿ ನಡೆಸಿ. ಮೊದಲು spec ಬರೆಯಿರಿ:
ಡ್ಯಾನಿಶ್ (
da) ಸೇರಿಸಿ. ಇಂಗ್ಲಿಷ್ನ ಅದೇ key ಗಳ ಜೊತೆsrc/content/da.jsಅನ್ನು ಒಂದು{ meta, pools, ui }bundle ಆಗಿ ರಚಿಸಿ, ಪ್ರತಿ entry ಅನ್ನು ಅನುವಾದಿಸುತ್ತಾ (content pool ಪ್ರತಿಯೊಂದೂ ~25, ಎಲ್ಲಾ UI string ಗಳು).src/lockedin.jsನಲ್ಲಿBUNDLESನಲ್ಲಿdaregister ಮಾಡಿ.--lang daಮತ್ತು ಒಂದುda-*locale ಇದನ್ನು ಆಯ್ಕೆ ಮಾಡಬೇಕು. card header string ಗಳನ್ನು width ಮಿತಿಯೊಳಗೆ ಇಡಿ.npm testಹಸಿರಾಗಿ ಉಳಿಯಬೇಕು, ಮತ್ತು ಅಸ್ತಿತ್ವದ localized ಗಳನ್ನು ಪ್ರತಿಬಿಂಬಿಸುವ ಡ್ಯಾನಿಶ್ invariant + detection test ಗಳನ್ನು ಸೇರಿಸಿ.
ನಂತರ ಅಧ್ಯಾಯ 3–4 ರ loop ಚಲಾಯಿಸಿ:
- ಮೊದಲು plan. "ಕೋಡ್ ಬರೆಯುವ ಮೊದಲು, ಯಾವ ಫೈಲ್ಗಳನ್ನು ಬದಲಾಯಿಸುತ್ತೀ ಮತ್ತು ಇಂಗ್ಲಿಷ್ ಜೊತೆ key parity ಅನ್ನು ಹೇಗೆ ಇಡುತ್ತೀ ಎಂದು ಹೇಳು."
-
ಮೊದಲು test ಗಳು. "failing test ಗಳನ್ನು ಸೇರಿಸು:
dadetection,daಗಾಗಿ key parity, ಮತ್ತು ಒಂದು ಡ್ಯಾನಿಶ್ reflect/connect invariant. bundle ಅನ್ನು ಇನ್ನೂ ರಚಿಸಬೇಡ." -
Implement. "ಈಗ ಒಂದು ಅಸ್ತಿತ್ವದ bundle ಅನ್ನು key ಗೆ key ಅನುವಾದಿಸಿ
src/content/da.jsರಚಿಸು, register ಮಾಡು, ಮತ್ತು test ಗಳನ್ನು ಪಾಸ್ ಮಾಡಿಸು. randomness ಗಾಗಿ ಕೇವಲpick/shuffle." -
ಗೇಟ್ + review.
npm test, ನಂತರlockedin --lang da post— ಮತ್ತು diff ಅನ್ನು ಓದಿ: ಪ್ರತಿ key ಅನುವಾದವಾಯಿತೇ? card border ಗಳು ಇನ್ನೂ line up ಆಗುತ್ತವೆಯೇ?{cap}ಇರುವ template ಗಳು raw user clause ಗಳಲ್ಲಿ ಉಳಿಯುತ್ತವೆಯೇ?
ಇಡೀ ಭಾಷೆ ತುಂಬಾ ಜಾಸ್ತಿ ಎನಿಸಿದರೆ ಚಿಕ್ಕ warm-up ಅಭ್ಯಾಸಗಳು:
- "ಎಲ್ಲಾ 33 language bundle ಗಳಿಗೆ ಇನ್ನೊಂದು
TAGLINEಸೇರಿಸು, count ಗಳನ್ನು ಸಮಾನವಾಗಿ ಇಡುತ್ತಾ." - "ಕನ್ನಡ
cardFooter≤ 60 visible column ಆಗಿದೆಯೇ ಎಂದು ಪರಿಶೀಲಿಸು ಮತ್ತು combining mark ಗಳನ್ನು ಹೇಗೆ ಅಳೆಯಲಾಯಿತು ಎಂದು ವಿವರಿಸು." - "
ja.jsನಿಂದ ಒಂದುuikey delete ಮಾಡಿದರೆ fail ಆಗುವ test ಅನ್ನು ತೋರಿಸು."
-
src/content/es.jsಅನ್ನು skim ಮಾಡಿ — ಇದು ಇನ್ನೂ ಒಂದು ಹೊಸ bundle ಗೆ ಸ್ನೇಹಪೂರ್ಣ template. -
docs/HANDOFF.md→ "Adding a language" ಅನ್ನು ಮತ್ತೆ ಓದಿ. - ಕಮಾಂಡ್ ರೆಫರೆನ್ಸ್ ನಲ್ಲಿ ಬಹುಭಾಷಾ ತಮಾಷೆಗಳನ್ನು ಆನಂದಿಸಿ.
ಅದೇ ಪೂರ್ಣ ಟ್ಯುಟೋರಿಯಲ್. ನೀವು ಈಗ ಒಂದು AI ಏಜೆಂಟ್ಗೆ feature ಗಳನ್ನು ಕಟ್ಟಲು ಮತ್ತು ಅವನ್ನು ಒಂದು test ಗೇಟ್ನ ಹಿಂದೆ localize ಮಾಡಲು ನಿರ್ದೇಶಿಸಬಲ್ಲಿರಿ — 33 ಭಾಷೆಗಳಲ್ಲಿ ಮತ್ತು ಇನ್ನಷ್ಟಕ್ಕೆ ಸಿದ್ಧ. Agree? 👇
Tutorial
- 1 · Orientation
- 2 · How the Code Works
- 3 · Your First Agent Task
- 4 · Prompting & Reviewing
- 5 · Localization
Reference
Satire · Sátira · 風刺. Not affiliated with LinkedIn. GPL-3.0-or-later.