
🔢 Tłumaczenie liczb z PHP i JavaScript: cyfry arabskie na dewanagari i z powrotem
Użytkownik wypełnia formularz na stronie, a cyfry zamieniają się w nieczytelne symbole. Znajoma sytuacja dla osób pracujących z projektami wielojęzycznymi: nepalska wersja sklepu internetowego pokazuje ceny w अक्षर, a formularz zwrotny nie przechodzi walidacji z powodu „nieprawidłowych" cyfr.
Problem polega na tym, że różne języki używają różnych systemów znaków liczbowych. Angielski i rosyjski: cyfry arabskie (0-9). Hindi, nepalski, marathi: znaki dewanagari (०-९). PHP i JavaScript „od razu po instalacji" nie przełączają się między nimi. Jednocześnie zadanie rozwiązuje się bez żadnej zewnętrznej biblioteki, wystarczą wbudowane funkcje do pracy z ciągami znaków. Żadnych podłączonych zależności, żadnych zewnętrznych API.
Poniżej dwa gotowe fragmenty kodu, które zamykają kwestię w 5 minut. Bez frameworków, bez pakietów Composera, bez zależności npm, na czystym PHP i waniliowym JavaScript. Kopiują Państwo, podstawiają swoje znaki i działa.
💡 Szybki przegląd:
- Proszę skopiować funkcję PHP do functions.php motywu lub przez wtyczkę Code Snippets, konwertuje ona cyfry arabskie na dewanagari i z powrotem
- Na frontendzie proszę użyć gotowego kodu JavaScript z obiektami-słownikami, konwersja w locie bezpośrednio w polu wprowadzania
- Zamiana odbywa się według tabeli zgodności glifów, a nie matematycznie, metoda jest uniwersalna dla każdego systemu pisma
- Proszę przetestować: proszę przekazać 1234 i otrzymać १२३४, i odwrotnie, obie strony działają symetrycznie
Jak zbudowane są systemy liczbowe w różnych językach
Większość stron pracuje z cyframi arabskimi: 0 1 2 3 4 5 6 7 8 9. Historycznie system ten przyszedł z Indii, ale utrwalił się za pośrednictwem świata arabskiego, stąd nazwa.
Alternatywne zestawy istnieją w dziesiątkach systemów pisma. Dewanagari (hindi, nepalski, marathi) używa własnego szeregu: ० १ २ ३ ४ ५ ६ ७ ८ ९. Cyfry wschodnioarabskie (arabski, perski, urdu) to inny zestaw: ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩. Bengalski, tajski, khmerski: każdy ma swoje glify i swoje zakresy w tabeli Unicode. Łącznie takich systemów jest ponad dwadzieścia.
Ale wartość liczbowa pozostaje ta sama. 5, ५ i ٥ to jedna i ta sama liczba „pięć", po prostu zapisana różnymi znakami. Dlatego tłumaczenie między systemami to zamiana glifów według tabeli zgodności, a nie konwersja matematyczna. Nic nie trzeba przeliczać, wystarczy znać poprawne pary znaków.
Właśnie ta zasada leży u podstaw kodu poniżej.
Krok 1: Tłumaczenie liczb za pomocą PHP

Podejście PHP jest maksymalnie proste: funkcja str_replace() przyjmuje dwie tablice: czego szukać i na co zamieniać. Ciąg znaków przechodzi jedno przejście i wszystkie dopasowania są zamieniane.
Proszę dodać ten kod do functions.php motywu potomnego lub przez wtyczkę Code Snippets. Funkcja przyjmuje liczbę lub ciąg znaków z cyframi i zwraca wynik ze znakami dewanagari.
1 <?php 2 /** 3 * Конвертирует арабские цифры в символы деванагари (хинди, непальский). 4 * 5 * @param string|int $input Строка или число для конвертации. 6 * @return string Строка с цифрами деванагари. 7 */ 8 function convert_to_devanagari($input) { 9 $english = array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); 10 $devanagari = array("०", "१", "२", "३", "४", "५", "६", "७", "८", "९"); 11 12 return str_replace($english, $devanagari, (string) $input); 13 } 14 15 /* Пример использования */ 16 echo convert_to_devanagari(2026); 17 // Вывод: २०२६ 18 ?>
Co tu się dzieje: str_replace() przechodzi po tablicy $english i dla każdego elementu (na przykład "2") podstawia odpowiedni element z $devanagari ("२"). Rzutowanie na (string) gwarantuje, że funkcja zadziała zarówno z liczbą, jak i z ciągiem znaków.
Konwersja odwrotna, z dewanagari na cyfry arabskie, odbywa się przez przestawienie tablic miejscami:
1 <?php 2 /** 3 * Конвертирует символы деванагари обратно в арабские цифры. 4 * 5 * @param string $input Строка с цифрами деванагари. 6 * @return string Строка с арабскими цифрами. 7 */ 8 function convert_from_devanagari($input) { 9 $english = array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9"); 10 $devanagari = array("०", "१", "२", "३", "४", "५", "६", "७", "८", "९"); 11 12 return str_replace($devanagari, $english, $input); 13 } 14 15 /* Пример */ 16 echo convert_from_devanagari('२०२६'); 17 // Вывод: 2026 18 ?>
Tablice są te same, zmienia się tylko kolejność argumentów. Pierwsza tablica zawiera teraz znaki dewanagari (to, czego szukamy), druga: cyfry arabskie (na co zamieniamy).
Gdzie zastosować. Funkcja przyda się w każdym miejscu motywu, gdzie wyświetlane są liczby: ceny towarów w WooCommerce, daty na blogu, numeracja stron. Proszę opakować wywołanie tam, gdzie potrzebna jest lokalizacja cyfr dla konkretnej grupy odbiorców.
Obsługa przypadków brzegowych w PHP
Funkcja convert_to_devanagari() przyjmuje string|int, ale w praktyce dane wejściowe mogą być dowolne. Co się stanie, jeśli przekażą Państwo null, pusty ciąg znaków lub ciąg bez cyfr? (string) null da pusty ciąg, str_replace() z pustym ciągiem również zwróci pusty, błędu nie będzie. Ciąg bez cyfr (na przykład "Привет") zostanie zwrócony bez zmian, zamiana po prostu nie znajdzie dopasowań.
Jeśli liczba zawiera separatory (przecinki dla tysięcy, kropkę dla części ułamkowej), pozostaną one na swoim miejscu, zamienione zostaną tylko same cyfry. Dla liczb zmiennoprzecinkowych to zachowanie jest poprawne, ale jeśli format liczb jest ważny i separatory powinny zmieniać się w zależności od ustawień regionalnych, proszę dodać osobną obsługę przez number_format() przed konwersją.
Dla bardzo długich liczb (na przykład 20-znakowe identyfikatory) podejście działa bez zmian: str_replace() przetwarza ciąg o dowolnej długości, ograniczeniem jest tylko dostępna pamięć PHP. Znaki dewanagari zajmują po 3 bajty w UTF-8, dlatego wynikowy ciąg będzie dłuższy od wyjściowego w bajtach. Do zliczania znaków proszę używać mb_strlen(), a nie strlen().
Krok 2: Tłumaczenie liczb za pomocą JavaScript
Na frontendzie ta sama logika jest realizowana przez obiekty-słowniki i metodę String.replace() z wyrażeniem regularnym. Jest to wygodne dla dynamicznych interfejsów: użytkownik wprowadza liczbę w polu, a skrypt w locie pokazuje ekwiwalent w dewanagari.
Proszę umieścić ten kod w osobnym pliku .js motywu lub przez wp_add_inline_script w functions.php. Żadnych zależności, czysty ES5, działa nawet w starych przeglądarkach.
1 /** 2 * Словари для перевода между арабскими цифрами и деванагари. 3 */ 4 var englishToDevanagari = { 5 '0': '०', '1': '१', '2': '२', '3': '३', '4': '४', 6 '5': '५', '6': '६', '7': '७', '8': '८', '9': '९' 7 }; 8 9 var devanagariToEnglish = { 10 '०': '0', '१': '1', '२': '2', '३': '3', '४': '4', 11 '५': '5', '६': '6', '७': '7', '८': '8', '९': '9' 12 }; 13 14 /** 15 * Конвертирует арабские цифры в строке в символы деванагари. 16 * @param {string|number} input 17 * @returns {string} 18 */ 19 function toDevanagari(input) { 20 return String(input).replace(/[0-9]/g, function(match) { 21 return englishToDevanagari[match]; 22 }); 23 } 24 25 /** 26 * Конвертирует символы деванагари в арабские цифры. 27 * @param {string} input 28 * @returns {string} 29 */ 30 function fromDevanagari(input) { 31 return input.replace(/[०-९]/g, function(match) { 32 return devanagariToEnglish[match]; 33 }); 34 } 35 36 // Примеры: 37 console.log(toDevanagari(9857)); // ९८५७ 38 console.log(fromDevanagari('१२३४')); // 1234
Kluczowy moment: wyrażenie regularne /[0-9]/g. Flaga g (global) zmusza replace() do przetworzenia każdej cyfry w ciągu, a nie tylko pierwszej. Anonimowa funkcja zwrotna otrzymuje dopasowany znak i zwraca jego ekwiwalent ze słownika.
Dla cyfr dewanagari używany jest zakres [०-९], w Unicode znaki te idą pod rząd, dlatego wyrażenie regularne działa poprawnie.
Gdzie zastosować. Wprowadzanie na żywo w formularzach (konwersja w locie podczas wpisywania), wyświetlanie cen i dat w zlokalizowanych wersjach strony, konwersja odwrotna przed wysłaniem formularza na serwer, aby do bazy zawsze trafiały cyfry arabskie.
Praktyczny przykład: formularz zwrotny z konwersją w locie
Zbierzmy oba podejścia w działającą całość. Załóżmy, że na nepalskiej wersji strony znajduje się formularz zamówienia, gdzie użytkownik wprowadza kwotę w dewanagari. Zadanie: pokazać wprowadzoną liczbę w obu systemach do weryfikacji i wysłać na serwer cyfry arabskie.
Znacznik formularza zawiera <input> i blok podglądu. Na każde naciśnięcie klawisza w polu uruchamia się procedura obsługi input, która wywołuje toDevanagari() i wyprowadza wynik do sąsiedniego <span>. Podczas wysyłania formularza uruchamia się fromDevanagari() i w treści żądania POST na serwer idą już cyfry arabskie. Część serwerowa w PHP otrzymuje liczbę w standardowym formacie i pracuje z nią jak zwykle, bez dodatkowej konwersji.
Ten sam szablon ma zastosowanie do pól cen, dat, numerów telefonów i wszelkich innych pól, gdzie użytkownik oczekuje zobaczyć rodzimy system cyfr, a system musi przechowywać ujednolicony format. Konwersja zajmuje mikrosekundy i nie wpływa na responsywność interfejsu.
Zobacz także: wideo o systemach liczbowych w programowaniu
Dla szerszego spojrzenia na temat, jak zbudowane są systemy liczbowe w kodzie i jak konwertować między nimi w JavaScript, proszę obejrzeć to omówienie od Techno Geek. Obejmuje system dwójkowy, ósemkowy i dziesiętny z gotowym projektem.
⁉️🤔 Często zadawane pytania
Czy tą samą metodą można przetłumaczyć cyfry na arabski (znaki wschodnioarabskie)?
Tak. Proszę zamienić tablicę dewanagari na znaki wschodnioarabskie:
array("٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩"). Logika jest ta sama,str_replace()w PHP i słownik z wyrażeniem regularnym w JS. Tak samo adaptuje się to pod bengalski, tajski, khmerski i każdy inny system pisma z własnymi glifami liczbowymi.
Czy bezpiecznie jest używać str_replace() dla ciągów wielobajtowych w PHP?
Tak,
str_replace()poprawnie pracuje z UTF-8 i znakami wielobajtowymi, w przeciwieństwie dostrpos()lubsubstr(), które potrzebują odpowiedników mbstring. Znaki dewanagari (२,३) zajmują po 3 bajty w UTF-8, alestr_replace()przetwarza je bajtowo-bezpiecznie, ponieważ szuka dokładnego binarnego dopasowania sekwencji. Problemów nie będzie.
Co zrobić, jeśli w ciągu są pomieszane cyfry arabskie i znaki dewanagari?
Obie funkcje przetwarzają tylko swoje zakresy. Jeśli na wejście
convert_to_devanagari()przyjdzie ciąg"Цена: 500 रुपей", cyfra500stanie się५००, a tekst pozostanie nietknięty. Funkcja odwrotnaconvert_from_devanagari()dotknie tylko cyfr dewanagari. Wprowadzanie mieszane jest przetwarzane poprawnie automatycznie.
Jak zastosować konwersję do wszystkich liczb na stronie WordPress bez edycji każdego szablonu?
Proszę użyć podejścia JavaScript z kroku 2 i uruchomić przechodzenie węzłów DOM podczas ładowania strony. Proszę znaleźć wszystkie węzły tekstowe z cyframi (przez
TreeWalkerlub rekurencyjne przechodzeniechildNodes), zastosowaćtoDevanagari()do zawartości. Dla podejścia PHP po stronie serwera: filtr nathe_contentlubgettext, jeśli liczby są osadzone w tłumaczeniach.
Skąd wziąć tabele znaków dla innych systemów pisma?
Autorytatywne źródło: Unicode Consortium. Dla cyfr dewanagari jest to zakres U+0966-U+096F. Wschodnioarabskie: U+0660-U+0669. Bengalskie: U+09E6-U+09EF. Wystarczy skopiować znaki z tabeli i podstawić do tablic, kodu zmieniać nie trzeba.
Wydajność i ograniczenia podejścia
str_replace() z tablicami 10 elementów wykonuje dokładnie 10 porównań dla każdej pozycji w ciągu. Dla typowego ciągu z 5-10 cyframi to 50-100 operacji, czas wykonania mierzy się w mikrosekundach. Dla porównania, podejście przez preg_replace_callback() z wyrażeniem regularnym dodaje narzut na kompilację wzorca i wywołanie funkcji zwrotnej dla każdego dopasowania. Różnica na małych ciągach jest niezauważalna, ale str_replace() wygrywa na dużych wolumenach.
Głównym ograniczeniem podejścia jest to, że zamienia ono glify, a nie semantykę liczby. Jeśli potrzebna będzie arytmetyka na liczbach w dewanagari (dodawanie, mnożenie), znaki dewanagari nie będą postrzegane przez PHP jako liczby. Zawsze proszę konwertować na cyfry arabskie przed operacjami matematycznymi i z powrotem po nich. Nie jest to wada metody, a konsekwencja różnicy między pismem a liczbowym typem danych.
Jeszcze jeden niuans: metoda zakłada jednoznaczną odpowiedniość „jeden glif, jedna cyfra". Dla systemów pisma, gdzie liczby zapisuje się złożonymi ligaturami (jak w niektórych systemach historycznych), podejście z prostą zamianą nie zadziała. Ale dla wszystkich współczesnych indyjskich systemów pisma (dewanagari, bengalski, gurmukhi, gudżarati, orija, tamilski, telugu, kannada, malajalam), a także dla cyfr wschodnioarabskich odpowiedniość jest ściśle 1 do 1 i metoda działa niezawodnie.
Co wdrażać na produkcję: PHP, JavaScript czy oba warianty?
Rozwiązanie PHP jest przeznaczone dla przypadków, gdy liczby muszą być wyrenderowane w wymaganym systemie znaków na serwerze przed wysłaniem HTML. Jest to poprawne dla SEO: wyszukiwarka widzi treść od razu w docelowych ustawieniach regionalnych, a nie cyfry arabskie, które potem są podmieniane przez skrypt. Dla sklepu internetowego na WooCommerce oznacza to, że ceny w katalogu i na karcie towaru są indeksowane z cyframi dewanagari, co pozytywnie wpływa na ranking w segmentach nepalskim i hindi.
Wariant JavaScript jest przeznaczony do dynamicznej interakcji: pole wprowadzania z natychmiastowym podglądem, przełączanie języka interfejsu bez przeładowania, konwersja danych formularza przed wysłaniem. Jest on również niezbędny dla aplikacji jednostronicowych (SPA), gdzie serwer zwraca JSON z cyframi arabskimi, a frontend renderuje je w ustawieniach regionalnych użytkownika.
W praktyce dobrze sprawdza się połączenie: PHP renderuje stronę z zlokalizowanymi cyframi do indeksacji, a JavaScript przechwytuje dane wprowadzane przez użytkownika i konwertuje tam i z powrotem w locie. Oba fragmenty kodu, bez zewnętrznych zależności, mają łącznie mniej niż 40 linii i zamykają zadanie całkowicie dla każdego systemu pisma z własnymi glifami liczbowymi.
Przed wdrożeniem na produkcję proszę sprawdzić trzy scenariusze: bezpośrednie wywołanie funkcji z liczbą, ciąg znaków z mieszaną zawartością (cyfry plus tekst) i konwersję odwrotną. Proszę upewnić się, że na serwer zawsze trafiają cyfry arabskie, a w interfejsie użytkownik widzi ten system, który odpowiada jego oczekiwaniom językowym. Pięć minut testowania oszczędza godziny debugowania na żywym ruchu.
Proszę skopiować oba fragmenty kodu do projektu, podstawić potrzebne znaki z tabeli Unicode dla swojego systemu pisma i zadanie jest zamknięte. Wszystko, co potrzebne, jest już wbudowane w język.



