Install via yarn add locutus and import:
import { strtr } from 'locutus/php/strings/strtr'.
Or with CommonJS: const { strtr } = require('locutus/php/strings/strtr')
Use a bundler that supports tree-shaking so you only ship the functions you actually use.
Vite,
webpack,
Rollup, and
Parcel
all handle this. For server-side use this is less of a concern.
Examples
These examples are extracted from test cases that automatically verify our functions against their native counterparts.
#
code
expected result
1
var $trans = {'hello' : 'hi', 'hi' : 'hello'}
strtr('hi all, I said hello', $trans)
'hello all, I said hi'
2
strtr('äaabaåccasdeöoo', 'äåö','aao')
'aaabaaccasdeooo'
3
strtr('ääääääää', 'ä', 'a')
'aaaaaaaa'
4
strtr('http', 'pthxyz','xyzpth')
'zyyx'
5
strtr('zyyx', 'pthxyz','xyzpth')
'http'
6
strtr('aa', {'a':1,'aa':2})
'2'
Dependencies
This function uses the following Locutus functions:
exportfunctionstrtr(str: string, trFrom: string | ReplacementMap | string[], trTo?: string | StrtrValue[]): string { // discuss at: https://locutus.io/php/strtr/ // original by: Brett Zamir (https://brett-zamir.me) // input by: uestla // input by: Alan C // input by: Taras Bogach // input by: jpfle // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Brett Zamir (https://brett-zamir.me) // example 1: var $trans = {'hello' : 'hi', 'hi' : 'hello'} // example 1: strtr('hi all, I said hello', $trans) // returns 1: 'hello all, I said hi' // example 2: strtr('äaabaåccasdeöoo', 'äåö','aao') // returns 2: 'aaabaaccasdeooo' // example 3: strtr('ääääääää', 'ä', 'a') // returns 3: 'aaaaaaaa' // example 4: strtr('http', 'pthxyz','xyzpth') // returns 4: 'zyyx' // example 5: strtr('zyyx', 'pthxyz','xyzpth') // returns 5: 'http' // example 6: strtr('aa', {'a':1,'aa':2}) // returns 6: '2'
let fr = '' let i = 0 let j = 0 let lenStr = 0 let lenFrom = 0 letsortByReference: IniValue | undefined = false let istr = '' consttmpFrom: string[] = [] consttmpTo: StrtrValue[] = [] let ret = '' let match = false
// Received replace_pairs? // Convert to normal trFrom->trTo chars if (typeof trFrom === 'object' && !Array.isArray(trFrom)) { // Not thread-safe; temporarily set to true // @todo: Don't rely on ini here, use internal krsort instead sortByReference = iniSet('locutus.sortByReference', false) const sorted = krsort(trFrom) iniSet('locutus.sortByReference', sortByReference)
if (typeof sorted === 'object') { for (fr in sorted) { if (sorted.hasOwnProperty(fr)) { tmpFrom.push(fr) tmpTo.push(sorted[fr]) } } }
exportfunctionstrtr(str, trFrom, trTo) { // discuss at: https://locutus.io/php/strtr/ // original by: Brett Zamir (https://brett-zamir.me) // input by: uestla // input by: Alan C // input by: Taras Bogach // input by: jpfle // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Brett Zamir (https://brett-zamir.me) // example 1: var $trans = {'hello' : 'hi', 'hi' : 'hello'} // example 1: strtr('hi all, I said hello', $trans) // returns 1: 'hello all, I said hi' // example 2: strtr('äaabaåccasdeöoo', 'äåö','aao') // returns 2: 'aaabaaccasdeooo' // example 3: strtr('ääääääää', 'ä', 'a') // returns 3: 'aaaaaaaa' // example 4: strtr('http', 'pthxyz','xyzpth') // returns 4: 'zyyx' // example 5: strtr('zyyx', 'pthxyz','xyzpth') // returns 5: 'http' // example 6: strtr('aa', {'a':1,'aa':2}) // returns 6: '2'
let fr = '' let i = 0 let j = 0 let lenStr = 0 let lenFrom = 0 let sortByReference = false let istr = '' const tmpFrom = [] const tmpTo = [] let ret = '' let match = false
// Received replace_pairs? // Convert to normal trFrom->trTo chars if (typeof trFrom === 'object' && !Array.isArray(trFrom)) { // Not thread-safe; temporarily set to true // @todo: Don't rely on ini here, use internal krsort instead sortByReference = iniSet('locutus.sortByReference', false) const sorted = krsort(trFrom) iniSet('locutus.sortByReference', sortByReference)
if (typeof sorted === 'object') { for (fr in sorted) { if (sorted.hasOwnProperty(fr)) { tmpFrom.push(fr) tmpTo.push(sorted[fr]) } } }
return { ini, locales, localeCategories, pointers, locale_default: localeDefault, } }
// php/i18n/i18n_loc_get_default (Locutus dependency module) functioni18n_loc_get_default(): string { // discuss at: https://locutus.io/php/i18n_loc_get_default/ // original by: Brett Zamir (https://brett-zamir.me) // note 1: Renamed in PHP6 from locale_get_default(). Not listed yet at php.net. // note 1: List of locales at <https://demo.icu-project.org/icu-bin/locexp> // note 1: To be usable with sort() if it is passed the `SORT_LOCALE_STRING` // note 1: sorting flag: https://php.net/manual/en/function.sort.php // example 1: i18n_loc_get_default() // returns 1: 'en_US_POSIX' // example 2: i18n_loc_set_default('pt_PT') // example 2: i18n_loc_get_default() // returns 2: 'pt_PT'
function_phpCastString(value: CastStringValue): string { // original by: Rafał Kukawski
if (typeof value === 'boolean') { return value ? '1' : '' } if (typeof value === 'string') { return value } if (typeof value === 'number') { if (isNaN(value)) { return'NAN' }
// Check which string ended first // return -1 if a, 1 if b, 0 otherwise if (iBeforeStrEnd && !jBeforeStrEnd) { return1 } if (!iBeforeStrEnd && jBeforeStrEnd) { return -1 } return0 }
function krsort<T>(inputArr: Record<string, T>, sortFlags?: SortFlag): boolean | Record<string, T> { // discuss at: https://locutus.io/php/krsort/ // original by: GeekFG (https://geekfg.blogspot.com) // improved by: Kevin van Zonneveld (https://kvz.io) // improved by: Brett Zamir (https://brett-zamir.me) // bugfixed by: pseudaria (https://github.com/pseudaria) // note 1: The examples are correct, this is a new way // note 1: This function deviates from PHP in returning a copy of the array instead // note 1: of acting by reference and returning true; this was necessary because // note 1: IE does not allow deleting and re-adding of properties without caching // note 1: of property position; you can set the ini of "locutus.sortByReference" to true to // note 1: get the PHP behavior, but use this only if you are in an environment // note 1: such as Firefox extensions where for-in iteration order is fixed and true // note 1: property deletion is supported. Note that we intend to implement the PHP // note 1: behavior by default if IE ever does allow it; only gives shallow copy since // note 1: is by reference in PHP anyways // note 1: Since JS objects' keys are always strings, and (the // note 1: default) SORT_REGULAR flag distinguishes by key type, // note 1: if the content is a numeric string, we treat the // note 1: "original type" as numeric. // example 1: var $data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'} // example 1: krsort($data) // example 1: var $result = $data // returns 1: {d: 'lemon', c: 'apple', b: 'banana', a: 'orange'} // example 2: ini_set('locutus.sortByReference', true) // example 2: var $data = {2: 'van', 3: 'Zonneveld', 1: 'Kevin'} // example 2: krsort($data) // example 2: var $result = $data // returns 2: {3: 'Zonneveld', 2: 'van', 1: 'Kevin'}
// Rebuild array with sorted key names for (i = 0; i < keys.length; i++) { const keyName = keys[i] if (typeof keyName === 'undefined') { continue } k = keyName const value = inputArr[k] if (sortByReference) { delete inputArr[k] } if (typeof value === 'undefined') { continue } tmpArr[k] = value } for (const i in tmpArr) { if (tmpArr.hasOwnProperty(i)) { const value = tmpArr[i] if (typeof value === 'undefined') { continue } populateArr[i] = value } }
const isIniScalar = (value: IniCandidate): value is IniScalar => typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null
const isIniObject = (value: IniCandidate): value is IniObject => typeof value === 'object' && value !== null && !Array.isArray(value)
const isIniArray = (value: IniCandidate): value is IniEntryValue[] => Array.isArray(value) && value.every((item: IniCandidate) =>isIniEntryValue(item))
const isIniEntryValue = (value: IniCandidate): value is IniEntryValue => isIniScalar(value) || isIniObject(value) || isIniArray(value)
const isIniValue = (value: IniCandidate): value is Exclude<IniValue, undefined> => isIniEntryValue(value)
functionini_set(varname: string, newvalue: IniValue): IniValue | undefined { // discuss at: https://locutus.io/php/ini_set/ // parity verified: PHP 8.3 // original by: Brett Zamir (https://brett-zamir.me) // note 1: This will not set a global_value or access level for the ini item // example 1: ini_set('date.timezone', 'Asia/Hong_Kong') // example 1: ini_set('date.timezone', 'America/Chicago') // returns 1: 'Asia/Hong_Kong'
constsetArrayValue = () => { // Although these are set individually, they are all accumulated. if (typeof entry.local_value === 'undefined') { entry.local_value = [normalizedValue] return }
if (Array.isArray(entry.local_value)) { entry.local_value.push(normalizedValue) return }
// php/strings/strtr (target function module) const iniSet = ini_set;
typeStrtrValue = PhpRuntimeValue
typeReplacementMap = PhpAssoc<StrtrValue>
functionstrtr(str: string, trFrom: string | ReplacementMap | string[], trTo?: string | StrtrValue[]): string { // discuss at: https://locutus.io/php/strtr/ // original by: Brett Zamir (https://brett-zamir.me) // input by: uestla // input by: Alan C // input by: Taras Bogach // input by: jpfle // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Brett Zamir (https://brett-zamir.me) // example 1: var $trans = {'hello' : 'hi', 'hi' : 'hello'} // example 1: strtr('hi all, I said hello', $trans) // returns 1: 'hello all, I said hi' // example 2: strtr('äaabaåccasdeöoo', 'äåö','aao') // returns 2: 'aaabaaccasdeooo' // example 3: strtr('ääääääää', 'ä', 'a') // returns 3: 'aaaaaaaa' // example 4: strtr('http', 'pthxyz','xyzpth') // returns 4: 'zyyx' // example 5: strtr('zyyx', 'pthxyz','xyzpth') // returns 5: 'http' // example 6: strtr('aa', {'a':1,'aa':2}) // returns 6: '2'
let fr = '' let i = 0 let j = 0 let lenStr = 0 let lenFrom = 0 letsortByReference: IniValue | undefined = false let istr = '' consttmpFrom: string[] = [] consttmpTo: StrtrValue[] = [] let ret = '' let match = false
// Received replace_pairs? // Convert to normal trFrom->trTo chars if (typeof trFrom === 'object' && !Array.isArray(trFrom)) { // Not thread-safe; temporarily set to true // @todo: Don't rely on ini here, use internal krsort instead sortByReference = iniSet('locutus.sortByReference', false) const sorted = krsort(trFrom) iniSet('locutus.sortByReference', sortByReference)
if (typeof sorted === 'object') { for (fr in sorted) { if (sorted.hasOwnProperty(fr)) { tmpFrom.push(fr) tmpTo.push(sorted[fr]) } } }
return { ini, locales, localeCategories, pointers, locale_default: localeDefault, } }
// php/i18n/i18n_loc_get_default (Locutus dependency module) functioni18n_loc_get_default() { // discuss at: https://locutus.io/php/i18n_loc_get_default/ // original by: Brett Zamir (https://brett-zamir.me) // note 1: Renamed in PHP6 from locale_get_default(). Not listed yet at php.net. // note 1: List of locales at <https://demo.icu-project.org/icu-bin/locexp> // note 1: To be usable with sort() if it is passed the `SORT_LOCALE_STRING` // note 1: sorting flag: https://php.net/manual/en/function.sort.php // example 1: i18n_loc_get_default() // returns 1: 'en_US_POSIX' // example 2: i18n_loc_set_default('pt_PT') // example 2: i18n_loc_get_default() // returns 2: 'pt_PT'
if (typeof value === 'boolean') { return value ? '1' : '' } if (typeof value === 'string') { return value } if (typeof value === 'number') { if (isNaN(value)) { return'NAN' }
// Check which string ended first // return -1 if a, 1 if b, 0 otherwise if (iBeforeStrEnd && !jBeforeStrEnd) { return1 } if (!iBeforeStrEnd && jBeforeStrEnd) { return -1 } return0 }
functionkrsort(inputArr, sortFlags) { // discuss at: https://locutus.io/php/krsort/ // original by: GeekFG (https://geekfg.blogspot.com) // improved by: Kevin van Zonneveld (https://kvz.io) // improved by: Brett Zamir (https://brett-zamir.me) // bugfixed by: pseudaria (https://github.com/pseudaria) // note 1: The examples are correct, this is a new way // note 1: This function deviates from PHP in returning a copy of the array instead // note 1: of acting by reference and returning true; this was necessary because // note 1: IE does not allow deleting and re-adding of properties without caching // note 1: of property position; you can set the ini of "locutus.sortByReference" to true to // note 1: get the PHP behavior, but use this only if you are in an environment // note 1: such as Firefox extensions where for-in iteration order is fixed and true // note 1: property deletion is supported. Note that we intend to implement the PHP // note 1: behavior by default if IE ever does allow it; only gives shallow copy since // note 1: is by reference in PHP anyways // note 1: Since JS objects' keys are always strings, and (the // note 1: default) SORT_REGULAR flag distinguishes by key type, // note 1: if the content is a numeric string, we treat the // note 1: "original type" as numeric. // example 1: var $data = {d: 'lemon', a: 'orange', b: 'banana', c: 'apple'} // example 1: krsort($data) // example 1: var $result = $data // returns 1: {d: 'lemon', c: 'apple', b: 'banana', a: 'orange'} // example 2: ini_set('locutus.sortByReference', true) // example 2: var $data = {2: 'van', 3: 'Zonneveld', 1: 'Kevin'} // example 2: krsort($data) // example 2: var $result = $data // returns 2: {3: 'Zonneveld', 2: 'van', 1: 'Kevin'}
const tmpArr = {} const keys = [] let sorter let i let k let sortByReference = false let populateArr = {}
const runtime = ensurePhpRuntimeState()
switch (sortFlags) { case'SORT_STRING': // compare items as strings sorter = function (a, b) { returnNumber(strnatcmp(b, a) ?? 0) } break case'SORT_LOCALE_STRING': { // compare items as strings, based on the current locale // (set with i18n_loc_set_default() as of PHP6) const loc = i18nlgd() const locale = runtime.locales[loc] if (locale?.sorting) { sorter = locale.sorting } break } case'SORT_NUMERIC': // compare items numerically sorter = function (a, b) { returnNumber(b) - Number(a) } break case'SORT_REGULAR': default: // compare items normally (don't change types) sorter = function (b, a) { const aFloat = parseFloat(a) const bFloat = parseFloat(b) const aNumeric = aFloat + '' === a const bNumeric = bFloat + '' === b if (aNumeric && bNumeric) { return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0 } elseif (aNumeric && !bNumeric) { return1 } elseif (!aNumeric && bNumeric) { return -1 } return a > b ? 1 : a < b ? -1 : 0 } break }
// Make a list of key names for (k in inputArr) { if (inputArr.hasOwnProperty(k)) { keys.push(k) } } keys.sort(sorter)
// Rebuild array with sorted key names for (i = 0; i < keys.length; i++) { const keyName = keys[i] if (typeof keyName === 'undefined') { continue } k = keyName const value = inputArr[k] if (sortByReference) { delete inputArr[k] } if (typeof value === 'undefined') { continue } tmpArr[k] = value } for (const i in tmpArr) { if (tmpArr.hasOwnProperty(i)) { const value = tmpArr[i] if (typeof value === 'undefined') { continue } populateArr[i] = value } }
return sortByReference || populateArr }
// php/info/ini_set (Locutus dependency module) constisIniScalar = (value) => typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean' || value === null
constisIniObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value)
functionini_set(varname, newvalue) { // discuss at: https://locutus.io/php/ini_set/ // parity verified: PHP 8.3 // original by: Brett Zamir (https://brett-zamir.me) // note 1: This will not set a global_value or access level for the ini item // example 1: ini_set('date.timezone', 'Asia/Hong_Kong') // example 1: ini_set('date.timezone', 'America/Chicago') // returns 1: 'Asia/Hong_Kong'
constsetArrayValue = () => { // Although these are set individually, they are all accumulated. if (typeof entry.local_value === 'undefined') { entry.local_value = [normalizedValue] return }
if (Array.isArray(entry.local_value)) { entry.local_value.push(normalizedValue) return }
// php/strings/strtr (target function module) const iniSet = ini_set
functionstrtr(str, trFrom, trTo) { // discuss at: https://locutus.io/php/strtr/ // original by: Brett Zamir (https://brett-zamir.me) // input by: uestla // input by: Alan C // input by: Taras Bogach // input by: jpfle // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Kevin van Zonneveld (https://kvz.io) // bugfixed by: Brett Zamir (https://brett-zamir.me) // bugfixed by: Brett Zamir (https://brett-zamir.me) // example 1: var $trans = {'hello' : 'hi', 'hi' : 'hello'} // example 1: strtr('hi all, I said hello', $trans) // returns 1: 'hello all, I said hi' // example 2: strtr('äaabaåccasdeöoo', 'äåö','aao') // returns 2: 'aaabaaccasdeooo' // example 3: strtr('ääääääää', 'ä', 'a') // returns 3: 'aaaaaaaa' // example 4: strtr('http', 'pthxyz','xyzpth') // returns 4: 'zyyx' // example 5: strtr('zyyx', 'pthxyz','xyzpth') // returns 5: 'http' // example 6: strtr('aa', {'a':1,'aa':2}) // returns 6: '2'
let fr = '' let i = 0 let j = 0 let lenStr = 0 let lenFrom = 0 let sortByReference = false let istr = '' const tmpFrom = [] const tmpTo = [] let ret = '' let match = false
// Received replace_pairs? // Convert to normal trFrom->trTo chars if (typeof trFrom === 'object' && !Array.isArray(trFrom)) { // Not thread-safe; temporarily set to true // @todo: Don't rely on ini here, use internal krsort instead sortByReference = iniSet('locutus.sortByReference', false) const sorted = krsort(trFrom) iniSet('locutus.sortByReference', sortByReference)
if (typeof sorted === 'object') { for (fr in sorted) { if (sorted.hasOwnProperty(fr)) { tmpFrom.push(fr) tmpTo.push(sorted[fr]) } } }
for (i = 0; i < lenStr; i++) { match = false if (fromStr) { istr = str.charAt(i) for (j = 0; j < lenFrom; j++) { if (istr === fromStr.charAt(j)) { match = true break } } } elseif (fromArr) { for (j = 0; j < lenFrom; j++) { const fromVal = fromArr[j] if (fromVal === undefined) { continue } if (str.substr(i, fromVal.length) === fromVal) { match = true // Fast forward i = i + fromVal.length - 1 break } } } if (match) { ret += toStr ? toStr.charAt(j) : toArr ? toArr[j] : '' } else { ret += str.charAt(i) } }
return ret }
Improve this function
Locutus is a community effort following
The McDonald's Theory:
we ship first iterations, hoping others will improve them.
If you see something that could be better, we'd love your contribution.