Add new functions: get IPs, strip UTF8 BOM from text, text updates

Add the following new static methods

Convert\Strings::stripUTF8BomBytes: removes the UTF8 BOM bytes from the beginning of a line
Used for CSV files created in Excel for the first header entry (line 0/row 0)

Get\Systen::getIpAddresses: gets all IP addresses for the the current access user
and returns an array

Moved the frontend folder detection from the first load config to the config.path.php

Cleaned up the translations JS scripts
This commit is contained in:
Clemens Schwaighofer
2024-09-03 09:49:01 +09:00
parent 2d71e760e8
commit ef80cba561
8 changed files with 118 additions and 59 deletions

View File

@@ -1,19 +1,20 @@
#!/usr/bin/env bash #!/usr/bin/env bash
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# Assume script is in 4dev/bin # Assume script is in 4dev/bin
base_folder="${BASE_FOLDER}../../www/"; base_folder="${BASE_FOLDER}../../www/";
# locale gettext po to mo translator master # locale gettext po to mo translator master
for file in $(ls -1 ${base_folder}../4dev/locale/*.po); do for file in "${base_folder}"../4dev/locale/*.po; do
file=$(basename $file .po); [[ -e "$file" ]] || break
file=$(basename "$file" .po);
locale=$(echo "${file}" | cut -d "-" -f 1); locale=$(echo "${file}" | cut -d "-" -f 1);
domain=$(echo "${file}" | cut -d "-" -f 2); domain=$(echo "${file}" | cut -d "-" -f 2);
echo "- Translate language file '${file}' for locale '${locale}' and domain '${domain}':"; echo "- Translate language file '${file}' for locale '${locale}' and domain '${domain}':";
if [ ! -d "${base_folder}/includes/locale/${locale}/LC_MESSAGES/" ]; then if [ ! -d "${base_folder}/includes/locale/${locale}/LC_MESSAGES/" ]; then
mkdir -p "${base_folder}/includes/locale/${locale}/LC_MESSAGES/"; mkdir -p "${base_folder}/includes/locale/${locale}/LC_MESSAGES/";
fi; fi;
msgfmt -o ${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo ${base_folder}../4dev/locale/${locale}-${domain}.po; msgfmt -o "${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo" "${base_folder}../4dev/locale/${locale}-${domain}.po";
done; done;
# __END__ # __END__

View File

@@ -2,16 +2,18 @@
# read source mo files and writes target js files in object form # read source mo files and writes target js files in object form
# check for ARG 1 is "mv" # check for ARG 1 is "no-move"
# then move the files directly and don't do manual check (don't create temp files) # then do not move the files directly for manual check
FILE_MOVE=0; FILE_MOVE=1;
if [ "${1}" = "mv" ]; then if [ "${1}" = "no-move" ]; then
echo "+++ CREATE TEMPORARY FILES +++";
FILE_MOVE=0;
else
echo "*** Direct write ***"; echo "*** Direct write ***";
FILE_MOVE=1;
fi; fi;
target=''; target='';
BASE_FOLDER=$(dirname $(readlink -f $0))"/"; BASE_FOLDER=$(dirname "$(readlink -f "$0")")"/";
# Assume script is in 4dev/bin # Assume script is in 4dev/bin
base_folder="${BASE_FOLDER}../../www/"; base_folder="${BASE_FOLDER}../../www/";
po_folder='../4dev/locale/' po_folder='../4dev/locale/'
@@ -26,7 +28,7 @@ if [ "${target}" == '' ]; then
echo "*** Non smarty ***"; echo "*** Non smarty ***";
TEXTDOMAINDIR=${base_folder}${mo_folder}. TEXTDOMAINDIR=${base_folder}${mo_folder}.
# default is admin # default is admin
TEXTDOMAIN=admin; TEXTDOMAIN="admin";
fi; fi;
js_folder="${TEXTDOMAIN}/layout/javascript/"; js_folder="${TEXTDOMAIN}/layout/javascript/";
@@ -44,15 +46,16 @@ if [ ${error} -eq 1 ]; then
fi; fi;
# locale gettext po to mo translator master # locale gettext po to mo translator master
for file in $(ls -1 ${base_folder}../4dev/locale/*.po); do for file in "${base_folder}"../4dev/locale/*.po; do
file=$(basename $file .po); [[ -e "$file" ]] || break
echo "Translate language ${file}"; file=$(basename "$file" .po);
locale=$(echo "${file}" | cut -d "-" -f 1); locale=$(echo "${file}" | cut -d "-" -f 1);
domain=$(echo "${file}" | cut -d "-" -f 2); domain=$(echo "${file}" | cut -d "-" -f 2);
echo "- Translate language file '${file}' for locale '${locale}' and domain '${domain}':";
if [ ! -d "${base_folder}/includes/locale/${locale}/LC_MESSAGES/" ]; then if [ ! -d "${base_folder}/includes/locale/${locale}/LC_MESSAGES/" ]; then
mkdir -p "${base_folder}/includes/locale/${locale}/LC_MESSAGES/"; mkdir -p "${base_folder}/includes/locale/${locale}/LC_MESSAGES/";
fi; fi;
msgfmt -o ${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo ${base_folder}${po_folder}${locale}-${domain}.po; msgfmt -o "${base_folder}/includes/locale/${locale}/LC_MESSAGES/${domain}.mo" "${base_folder}${po_folder}${locale}-${domain}.po";
done; done;
rx_msgid_empty="^msgid \"\""; rx_msgid_empty="^msgid \"\"";
@@ -62,7 +65,7 @@ rx_msgstr="^msgstr \""
# quick copy string at the end # quick copy string at the end
quick_copy=''; quick_copy='';
for language in ${language_list[*]}; do for language in "${language_list[@]}"; do
# I don't know which one must be set, but I think at least LANGUAGE # I don't know which one must be set, but I think at least LANGUAGE
case ${language} in case ${language} in
ja) ja)
@@ -79,7 +82,8 @@ for language in ${language_list[*]}; do
esac; esac;
# write only one for language and then symlink files # write only one for language and then symlink files
template_file=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##//" | sed -e "s/##LANGUAGE##/${LANG}/"); template_file=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##//" | sed -e "s/##LANGUAGE##/${LANG}/");
original_file=$(echo ${template_file} | sed -e 's/\.TMP//g'); # original_file=$(echo ${template_file} | sed -e 's/\.TMP//g');
original_file=${template_file//.TMP/};
if [ "${FILE_MOVE}" -eq 0 ]; then if [ "${FILE_MOVE}" -eq 0 ]; then
file=${target_folder}${template_file}; file=${target_folder}${template_file};
else else
@@ -88,16 +92,18 @@ for language in ${language_list[*]}; do
echo "===> Write translation file ${file}"; echo "===> Write translation file ${file}";
echo ". = normal, : = escape, x = skip"; echo ". = normal, : = escape, x = skip";
# init line [aka don't touch this file] # init line [aka don't touch this file]
echo "// AUTO FILL, changes will be overwritten" > $file; echo "// AUTO FILL, changes will be overwritten" > "$file";
echo "// source: ${suffix}, language: ${language}" >> $file; {
echo "// Translation strings in the format" >> $file; echo "// source: ${suffix}, language: ${language}";
echo "// \"Original\":\"Translated\""$'\n' >> $file; echo "// Translation strings in the format";
echo "var i18n = {" >> $file; echo "// \"Original\":\"Translated\""$'\n'
echo "var i18n = {"
} >> "$file"
# translations stuff # translations stuff
# read the po file # read the po file
pos=0; # do we add a , for the next line pos=0; # do we add a , for the next line
cat "${base_folder}${po_folder}${language}-${TEXTDOMAIN}.po" | cat "${base_folder}${po_folder}${language}-${TEXTDOMAIN}.po" |
while read str; do while read -r str; do
# echo "S: ${str}"; # echo "S: ${str}";
# skip empty # skip empty
if [[ "${str}" =~ ${rx_msgid_empty} ]]; then if [[ "${str}" =~ ${rx_msgid_empty} ]]; then
@@ -112,12 +118,13 @@ for language in ${language_list[*]}; do
str_source=$(echo "${str}" | sed -e "s/^msgid \"//" | sed -e "s/\"$//"); str_source=$(echo "${str}" | sed -e "s/^msgid \"//" | sed -e "s/\"$//");
# close right side, if not last add , # close right side, if not last add ,
if [ "${pos}" -eq 1 ]; then if [ "${pos}" -eq 1 ]; then
echo -n "," >> $file; echo -n "," >> "$file";
fi; fi;
# all " inside string need to be escaped # all " inside string need to be escaped
str_source=$(echo "${str_source}" | sed -e 's/"/\\"/g'); # str_source=$(echo "${str_source}" | sed -e 's/"/\\"/g');
str_source=${str_source//\"/\\\"}
# fix with proper layout # fix with proper layout
echo -n "\"$str_source\":\"$(TEXTDOMAINDIR=${TEXTDOMAINDIR} LANGUAGE=${language} LANG=${LANG} gettext ${TEXTDOMAIN} "${str_source}")\"" >> $file; echo -n "\"$str_source\":\"$(TEXTDOMAINDIR=${TEXTDOMAINDIR} LANGUAGE=${language} LANG=${LANG} gettext "${TEXTDOMAIN}" "${str_source}")\"" >> "$file";
pos=1; pos=1;
elif [[ "${str}" =~ ${rx_msgstr} ]]; then elif [[ "${str}" =~ ${rx_msgstr} ]]; then
# open right side (ignore) # open right side (ignore)
@@ -128,8 +135,8 @@ for language in ${language_list[*]}; do
fi; fi;
done; done;
echo "" >> $file; echo "" >> "$file";
echo "};" >> $file; echo "};" >> "$file";
echo " [DONE]"; echo " [DONE]";
# on no move # on no move
@@ -140,19 +147,19 @@ for language in ${language_list[*]}; do
fi; fi;
# symlink to master file # symlink to master file
for suffix in ${source_list[*]}; do for suffix in "${source_list[@]}"; do
# symlink with full lang name # symlink with full lang name
symlink_file[0]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANG}/" | sed -e 's/\.TMP//g'); symlink_file[0]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANG}/" | sed -e 's/\.TMP//g');
# create second one with lang (no country) + encoding # create second one with lang (no country) + encoding
symlink_file[1]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANGUAGE}\.${ENCODING}/" | sed -e 's/\.TMP//g'); symlink_file[1]=$(echo ${template_file_stump} | sed -e "s/##SUFFIX##/${suffix}_/" | sed -e "s/##LANGUAGE##/${LANGUAGE}\.${ENCODING}/" | sed -e 's/\.TMP//g');
for template_file in ${symlink_file[@]}; do for template_file in "${symlink_file[@]}"; do
# if this is not symlink, create them # if this is not symlink, create them
if [ ! -h "${template_file}" ]; then if [ ! -h "${template_file}" ]; then
echo "Create symlink: ${template_file}"; echo "Create symlink: ${template_file}";
# symlik to original # symlik to original
cd "${target_folder}"; cd "${target_folder}" || exit;
ln -sf "${original_file}" "${template_file}"; ln -sf "${original_file}" "${template_file}";
cd - >/dev/null; cd - >/dev/null || exit;
fi; fi;
done; done;
done; done;

View File

@@ -1,4 +1,4 @@
<?php <?php // phpcs:ignore PSR1.Files.SideEffects
/******************************************************************** /********************************************************************
* AUTHOR: Clemens Schwaighofer * AUTHOR: Clemens Schwaighofer
@@ -11,6 +11,20 @@
declare(strict_types=1); declare(strict_types=1);
// find trigger name "admin/" or "frontend/" in the getcwd() folder
$folder = '';
foreach (['admin', 'frontend'] as $_folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
$folder = $_folder;
break;
}
}
// if content path is empty, fallback is default
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// File and Folder paths // File and Folder paths
// ID is TARGET (first array element) // ID is TARGET (first array element)
/*$PATHS = [ /*$PATHS = [

View File

@@ -1,4 +1,4 @@
<?php // phpcs:ignore warning <?php // phpcs:ignore PSR1.Files.SideEffects
/******************************************************************** /********************************************************************
* AUTHOR: Clemens Schwaighofer * AUTHOR: Clemens Schwaighofer
@@ -53,19 +53,6 @@ for (
\gullevek\dotEnv\DotEnv::readEnvFile( \gullevek\dotEnv\DotEnv::readEnvFile(
$__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH
); );
// find trigger name "admin/" or "frontend/" in the getcwd() folder
$folder = '';
foreach (['admin', 'frontend'] as $_folder) {
if (strstr(getcwd() ?: '', DIRECTORY_SEPARATOR . $_folder)) {
$folder = $_folder;
break;
}
}
// if content path is empty, fallback is default
if (empty($folder)) {
$folder = 'default';
}
define('CONTENT_PATH', $folder . DIRECTORY_SEPARATOR);
// load master config file that loads all other config files // load master config file that loads all other config files
require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php'; require $__DIR__PATH . $CONFIG_PATH_PREFIX . CONFIG_PATH . 'config.master.php';
break; break;

View File

@@ -134,6 +134,18 @@ class Strings
$path $path
) ?? $path; ) ?? $path;
} }
/**
* Remove UTF8 BOM Byte string from line
* Note: this is often found in CSV files exported from Excel at the first row, first element
*
* @param string $text
* @return string
*/
public static function stripUTF8BomBytes(string $text): string
{
return trim($text, pack('H*', 'EFBBBF'));
}
} }
// __END__ // __END__

View File

@@ -2402,7 +2402,7 @@ class IO
// flag if we have cache data stored at the moment // flag if we have cache data stored at the moment
'cached' => false, 'cached' => false,
// when fetch array or cache read returns false // when fetch array or cache read returns false
// in loop read that means dbReturn retuns false without erro // in loop read that means dbReturn retuns false without error
'finished' => false, 'finished' => false,
// read from cache/db (pos == rows) // read from cache/db (pos == rows)
'read_finished' => false, 'read_finished' => false,

View File

@@ -116,6 +116,29 @@ class System
3 3
) === 'cli' ? true : false; ) === 'cli' ? true : false;
} }
/**
* Collect all IP addresses
* REMOTE_ADDR, HTTP_X_FORWARD_FOR, CLIENT_IP
* and retuns them in an array with index of io source
* if address source has addresses with "," will add "-array" with these as array block
*
* @return array
*/
public static function getIpAddresses(): array
{
$ip_addr = [];
foreach (['REMOTE_ADDR', 'HTTP_X_FORWARDED_FOR', 'CLIENT_IP'] as $_ip_source) {
if (!empty($_SERVER[$_ip_source])) {
$ip_addr[$_ip_source] = $_SERVER[$_ip_source];
// same level as ARRAY IF there is a , inside
if (strstr($_SERVER[$_ip_source], ',') !== false) {
$ip_addr[$_ip_source . '-array'] = explode(',', $_SERVER[$_ip_source]);
}
}
}
return $ip_addr;
}
} }
// __END__ // __END__

View File

@@ -19,7 +19,7 @@ use CoreLibs\Template\HtmlBuilder\General\HtmlBuilderExcpetion;
class Block class Block
{ {
/** /**
* Undocumented function * Create Element
* *
* @param string $tag * @param string $tag
* @param string $id * @param string $id
@@ -86,7 +86,7 @@ class Block
} }
/** /**
* Undocumented function * Add multiple elements to the base element
* *
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $base * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $base
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} ...$attach * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} ...$attach
@@ -101,7 +101,7 @@ class Block
} }
/** /**
* Undocumented function * Add multiple sub elements to the base element
* *
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $sub * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $sub
@@ -117,7 +117,7 @@ class Block
} }
/** /**
* Undocumented function * Remove all sub element entries
* *
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} * @return array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}
@@ -131,7 +131,7 @@ class Block
// CSS Elements // CSS Elements
/** /**
* Undocumented function * Add css entry to the css entries
* *
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @param string ...$css * @param string ...$css
@@ -144,7 +144,7 @@ class Block
} }
/** /**
* Undocumented function * Remove a css entry entry from the css array
* *
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $element
* @param string ...$css * @param string ...$css
@@ -157,7 +157,7 @@ class Block
} }
/** /**
* Undocumented function * Switch CSS entries
* scssel (switch) is not supported * scssel (switch) is not supported
* use rcssel -> acssel * use rcssel -> acssel
* *
@@ -175,7 +175,7 @@ class Block
} }
/** /**
* Undocumented function * Build HTML from the content tree
* alias phfo * alias phfo
* *
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $tree * @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $tree
@@ -231,7 +231,23 @@ class Block
} }
/** /**
* Undocumented function * Alias for phfo
*
* @param array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>} $tree
* @param bool $add_nl [default=false]
* @return string
*
* @param array $tree
* @param bool $add_nl
* @return string
*/
public static function phfo(array $tree, bool $add_nl = false): string
{
return self::buildHtml($tree, $add_nl);
}
/**
* Build HTML elements from an array of elements
* alias phfa * alias phfa
* *
* @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list * @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list
@@ -248,8 +264,7 @@ class Block
} }
/** /**
* Undocumented function * alias for buildHtmlFromList
* wrapper for buildHtmlFromList
* *
* @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list array of Elements to build string from * @param array<array{tag:string,id:string,name:string,content:string,css:array<string>,options:array<string,string>,sub:array<mixed>}> $list array of Elements to build string from
* @param bool $add_nl [default=false] Optional output string line break * @param bool $add_nl [default=false] Optional output string line break