@ -18,7 +18,7 @@
* Helper functions converting moodle strings to json .
*/
function detect_languages ( $languages , $keys ) {
function detect_languages ( $languages ) {
echo " \n \n \n " ;
$all_languages = glob ( LANGPACKSFOLDER . '/*' , GLOB_ONLYDIR );
@ -32,10 +32,9 @@ function detect_languages($languages, $keys) {
$all_languages = array_filter ( $all_languages , 'get_lang_not_wp' );
$detect_lang = array_diff ( $all_languages , $languages );
$new_langs = array () ;
$new_langs = [] ;
foreach ( $detect_lang as $lang ) {
reset_translations_strings ();
$new = detect_lang ( $lang , $keys );
$new = detect_lang ( $lang );
if ( $new ) {
$new_langs [ $lang ] = $lang ;
}
@ -44,12 +43,10 @@ function detect_languages($languages, $keys) {
return $new_langs ;
}
function build_languages ( $languages , $ keys, $ added_langs = []) {
function build_languages ( $languages , $ added_langs = []) {
// Process the languages.
foreach ( $languages as $lang ) {
reset_translations_strings ();
$ok = build_lang ( $lang , $keys );
if ( $ok ) {
if ( build_lang ( $lang )) {
$added_langs [ $lang ] = $lang ;
}
}
@ -57,53 +54,70 @@ function build_languages($languages, $keys, $added_langs = []) {
return $added_langs ;
}
function get_langindex_keys () {
$local = 0 ;
// Process the index file, just once.
$keys = file_get_contents ( 'langindex.json' );
$keys = ( array ) json_decode ( $keys );
/**
* Loads lang index keys .
*/
function load_langindex () {
global $STATS ;
global $LANGINDEX ;
foreach ( $keys as $key => $value ) {
$map = new StdClass ();
if ( $value == 'local_moodlemobileapp' ) {
$map -> file = $value ;
$map -> string = $key ;
$local = 0 ;
$total = 0 ;
// Process the index file, just once.
$langindexjson = load_json ( 'langindex.json' );
$LANGINDEX = [];
foreach ( $langindexjson as $appkey => $value ) {
if ( $value == APPMODULENAME ) {
$file = $value ;
$lmskey = $appkey ;
$local ++ ;
} else {
$exp = explode ( '/' , $value , 2 );
$map -> file = $exp [ 0 ];
$ file = $exp [ 0 ];
if ( count ( $exp ) == 2 ) {
$ map-> string = $exp [ 1 ];
$ lmskey = $exp [ 1 ];
} else {
$exp = explode ( '.' , $ key, 3 );
$exp = explode ( '.' , $ app key, 3 );
if ( count ( $exp ) == 3 ) {
$ map-> string = $exp [ 2 ];
$ lmskey = $exp [ 2 ];
} else {
$ map-> string = $exp [ 1 ];
$ lmskey = $exp [ 1 ];
}
}
}
$keys [ $key ] = $map ;
if ( ! isset ( $LANGINDEX [ $file ])) {
$LANGINDEX [ $file ] = [];
}
$LANGINDEX [ $file ][ $appkey ] = $lmskey ;
$total ++ ;
}
$total = count ( $keys );
echo " Total strings to translate $total ( $local local) \n " ;
$STATS = new StdClass ();
$STATS -> local = $local ;
$STATS -> total = $total ;
return $keys ;
echo " Total strings to translate $total ( $local local) \n " ;
}
/**
* Add lang names to config file .
*
* @ param $langs Array of language codes to add .
* @ param $config Loaded config file .
*/
function add_langs_to_config ( $langs , $config ) {
$changed = false ;
$config_langs = get_object_vars ( $config [ 'languages' ]);
foreach ( $langs as $lang ) {
if ( ! isset ( $config_langs [ $lang ])) {
$langfoldername = str_replace ( '-' , '_' , $lang );
$langfoldername = get_langfolder( $lang );
$string = [];
include ( LANGPACKSFOLDER . '/' . $langfoldername . '/langconfig.php' );
$config [ 'languages' ] -> $lang = $string [ 'thislanguage' ];
$lmsstring = get_translation_strings ( $langfoldername , 'langconfig' );
$config [ 'languages' ] -> $lang = $lmsstring [ 'thislanguage' ];
$changed = true ;
}
}
@ -119,11 +133,31 @@ function add_langs_to_config($langs, $config) {
/**
* Save json data .
*
* @ param $path Path of the file to load .
* @ param $content Content string to save .
*/
function save_json ( $path , $content ) {
file_put_contents ( $path , str_replace ( '\/' , '/' , json_encode ( $content , JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT )) . " \n " );
}
/**
* Load json data .
*
* @ param $path Path of the file to load .
* @ return Associative array obtained from json .
*/
function load_json ( $path ) {
$file = file_get_contents ( $path );
return ( array ) json_decode ( $file );
}
/**
* Get ' s lang folder from lang code .
*
* @ param $lang Lang code .
* @ return Folder path .
*/
function get_langfolder ( $lang ) {
$folder = LANGPACKSFOLDER . '/' . str_replace ( '-' , '_' , $lang );
if ( ! is_dir ( $folder ) || ! is_file ( $folder . '/langconfig.php' )) {
@ -133,49 +167,56 @@ function get_langfolder($lang) {
return $folder ;
}
/**
* Import translation file from langpack and returns it .
*
* @ param $langfoldername Lang folder path .
* @ param $file File name ( excluding extension ) .
* @ param $override_folder If needed , the folder of the file to override strings .
* @ return String array .
*/
function get_translation_strings ( $langfoldername , $file , $override_folder = false ) {
global $strings ;
if ( isset ( $strings [ $file ])) {
return $strings [ $file ];
$lmsstring = import_translation_strings ( $langfoldername , $file ) ;
if ( $override_folder ) {
$override = import_translation_strings ( $override_folder , $file );
$lmsstring = array_merge ( $lmsstring , $override ) ;
}
$string = import_translation_strings ( $langfoldername , $file );
$string_override = $override_folder ? import_translation_strings ( $override_folder , $file ) : false ;
if ( $string ) {
$strings [ $file ] = $string ;
if ( $string_override ) {
$strings [ $file ] = array_merge ( $strings [ $file ], $string_override );
}
} else if ( $string_override ) {
$strings [ $file ] = $string_override ;
} else {
$strings [ $file ] = false ;
}
return $strings [ $file ];
return $lmsstring ;
}
/**
* Import translation file from langpack and returns it .
*
* @ param $langfoldername Lang folder path .
* @ param $file File name ( excluding extension ) .
* @ return String array .
*/
function import_translation_strings ( $langfoldername , $file ) {
$path = $langfoldername . '/' . $file . '.php' ;
// Apply translations.
if ( ! file_exists ( $path )) {
return false ;
return [] ;
}
$string = [];
include ( $path );
return $string ;
}
function reset_translations_strings () {
global $strings ;
$strings = [];
}
/**
* Build translations files from langpack .
*
* @ param lang Language code .
* @ return Wether it succeeded .
*/
function build_lang ( $lang ) {
global $STATS ;
global $LANGINDEX ;
function build_lang ( $lang , $keys ) {
$langfoldername = get_langfolder ( $lang );
if ( ! $langfoldername ) {
echo " Cannot translate $lang , folder not found " ;
@ -189,7 +230,7 @@ function build_lang($lang, $keys) {
$override_langfolder = false ;
}
$total = count ( $keys ) ;
$total = $STATS -> total ;
$local = 0 ;
$langparts = explode ( '-' , $lang , 2 );
@ -204,71 +245,71 @@ function build_lang($lang, $keys) {
}
$langFile = false ;
// Not yet translated. Do not override.
if ( file_exists ( ASSETSPATH . $lang . '.json' )) {
// Load lang files just once.
$langFile = file_get_contents ( ASSETSPATH . $lang . '.json' );
$langFile = ( array ) json_decode ( $langFile );
$langFile = load_json ( ASSETSPATH . $lang . '.json' );
}
$translations = [];
// Add the translation to the array.
foreach ( $keys as $key => $value ) {
$string = get_translation_strings ( $langfoldername , $value -> file , $override_langfolder );
// Apply translations.
if ( ! $string ) {
if ( $value -> file == 'donottranslate' ) {
// Restore it form the json.
if ( $langFile && is_array ( $langFile ) && isset ( $langFile [ $key ])) {
$translations [ $key ] = $langFile [ $key ];
} else {
// If not present, do not count it in the total.
$total -- ;
foreach ( $LANGINDEX as $file => $keys ) {
$lmsstring = get_translation_strings ( $langfoldername , $file , $override_langfolder );
foreach ( $keys as $appkey => $lmskey ) {
// Apply translations.
if ( empty ( $lmsstring )) {
if ( $file == 'donottranslate' ) {
// Restore it form the json.
if ( $langFile && is_array ( $langFile ) && isset ( $langFile [ $appkey ])) {
$translations [ $appkey ] = $langFile [ $appkey ];
} else {
// If not present, do not count it in the total.
$total -- ;
}
continue ;
}
if ( TOTRANSLATE ) {
echo " \n \t \t To translate $lmskey on $file " ;
}
continue ;
}
if ( TOTRANSLATE ) {
echo " \n \t \t To translate $value->string on $value->file " ;
}
continue ;
}
if ( ! isset ( $lmsstring [ $lmskey ]) || ( $lang == 'en' && $file == APPMODULENAME )) {
// Not yet translated. Do not override.
if ( $langFile && is_array ( $langFile ) && isset ( $langFile [ $appkey ])) {
$translations [ $appkey ] = $langFile [ $appkey ];
if ( ! isset ( $string [ $value -> string ]) || ( $lang == 'en' && $value -> file == 'local_moodlemobileapp' )) {
// Not yet translated. Do not override.
if ( $langFile && is_array ( $langFile ) && isset ( $langFile [ $key ])) {
$translations [ $key ] = $langFile [ $key ];
if ( $value -> file == 'local_moodlemobileapp' ) {
$local ++ ;
if ( $file == APPMODULENAME ) {
$local ++ ;
}
}
if ( TOTRANSLATE && ! isset ( $lmsstring [ $lmskey ])) {
echo " \n \t \t To translate $lmskey on $file " ;
}
continue ;
}
if ( TOTRANSLATE && ! isset ( $string [ $value -> string ])) {
echo " \n \t \t To translate $value->string on $value->file " ;
}
continue ;
} else {
$text = $string [ $value -> string ];
}
if ( $value -> file != 'local_moodlemobileapp' ) {
$text = str_replace ( '$a->@' , '$a.' , $text );
$text = str_replace ( '$a->' , '$a.' , $text );
$text = str_replace ( '{$a' , '{{$a' , $text );
$text = str_replace ( '}' , '}}' , $text );
$text = preg_replace ( '/@@.+?@@(<br>)?\\s*/' , '' , $text );
// Prevent double.
$text = str_replace ( array ( '{{{' , '}}}' ), array ( '{{' , '}}' ), $text );
} else {
// @TODO: Remove that line when core.cannotconnect and core.login.invalidmoodleversion are completelly changed to use $a
if (( $key == 'core.cannotconnect' || $key == 'core.login.invalidmoodleversion' ) && strpos ( $text , '2.4' ) != false ) {
$text = str_replace ( '2.4' , '{{$a}}' , $text );
}
$local ++ ;
}
$text = $lmsstring [ $lmskey ];
$translations [ $key ] = html_entity_decode ( $text );
if ( $file != APPMODULENAME ) {
$text = str_replace ( '$a->@' , '$a.' , $text );
$text = str_replace ( '$a->' , '$a.' , $text );
$text = str_replace ( '{$a' , '{{$a' , $text );
$text = str_replace ( '}' , '}}' , $text );
$text = preg_replace ( '/@@.+?@@(<br>)?\\s*/' , '' , $text );
// Prevent double.
$text = str_replace ([ '{{{' , '}}}' ], [ '{{' , '}}' ], $text );
} else {
// @TODO: Remove that line when core.cannotconnect and core.login.invalidmoodleversion are completelly changed to use $a
if (( $appkey == 'core.cannotconnect' || $appkey == 'core.login.invalidmoodleversion' ) && strpos ( $text , '2.4' ) != false ) {
$text = str_replace ( '2.4' , '{{$a}}' , $text );
}
$local ++ ;
}
$translations [ $appkey ] = html_entity_decode ( $text );
}
}
if ( ! empty ( $parent )) {
@ -290,19 +331,35 @@ function build_lang($lang, $keys) {
echo " \t \t $success of $total -> $percentage % $bar ( $local local) \n " ;
if ( $lang == 'en' ) {
generate_local_mo odlemobileapp( $keys , $translations );
override_component_lang_files ( $ keys, $ translations);
generate_local_mo dule_file( $LANGINDEX [ APPMODULENAME ] , $translations );
override_component_lang_files ( $ translations);
}
return true ;
}
function progressbar ( $percentage ) {
$done = floor ( $percentage / 10 );
return " \t " . str_repeat ( '=' , $done ) . str_repeat ( '-' , 10 - $done );
/**
* Generates an ASCII progress bar .
*
* @ param $percentage Done part .
* @ param $length Length of the text .
* @ return Text generated .
*/
function progressbar ( $percentage , $length = 10 ) {
$done = floor ( $percentage / $length );
return " \t " . str_repeat ( '=' , $done ) . str_repeat ( '-' , $length - $done );
}
function detect_lang ( $lang , $keys ) {
/**
* Check translations on langpack and detects if the language should be added .
*
* @ param lang Language code .
* @ return If the file should be added to the app .
*/
function detect_lang ( $lang ) {
global $STATS ;
global $LANGINDEX ;
$langfoldername = get_langfolder ( $lang );
if ( ! $langfoldername ) {
echo " Cannot translate $lang , folder not found " ;
@ -310,13 +367,13 @@ function detect_lang($lang, $keys) {
return false ;
}
$total = count ( $keys ) ;
$total = $STATS -> total ;
$success = 0 ;
$local = 0 ;
$ string = get_translation_strings ( $langfoldername , 'langconfig' );
$parent = isset ( $ string[ 'parentlanguage' ]) ? $ string[ 'parentlanguage' ] : " " ;
if ( ! isset ( $ string[ 'thislanguage' ])) {
$ lms string = get_translation_strings ( $langfoldername , 'langconfig' );
$parent = isset ( $ lms string[ 'parentlanguage' ]) ? $ lms string[ 'parentlanguage' ] : " " ;
if ( ! isset ( $ lms string[ 'thislanguage' ])) {
echo " Cannot translate $lang , translated name not found " ;
return false ;
}
@ -325,51 +382,66 @@ function detect_lang($lang, $keys) {
if ( $parent != " " && $parent != $lang ) {
$title .= " ( $parent ) " ;
}
$langname = $ string[ 'thislanguage' ];
$langname = $ lms string[ 'thislanguage' ];
$title .= " " . $langname . " -D " ;
// Add the translation to the array.
foreach ( $keys as $key => $value ) {
$string = get_translation_strings ( $langfoldername , $value -> file );
// Apply translations.
if ( ! $string ) {
// Do not count non translatable in the totals.
if ( $value -> file == 'donottranslate' ) {
$total -- ;
$lmsstring = get_translation_strings ( $langfoldername , APPMODULENAME );
if ( ! empty ( $lmsstring )) {
// Add the translation to the array.
foreach ( $LANGINDEX as $file => $keys ) {
$lmsstring = get_translation_strings ( $langfoldername , $file );
// Apply translations.
if ( empty ( $lmsstring )) {
// Do not count non translatable in the totals.
if ( $file == 'donottranslate' ) {
$total -= count ( $keys );
}
continue ;
}
continue ;
}
if ( ! isset ( $string [ $value -> string ])) {
continue ;
} else {
$text = $string [ $value -> string ];
}
foreach ( $keys as $lmskey ) {
if ( ! isset ( $lmsstring [ $lmskey ])) {
continue ;
}
if ( $value -> file == 'local_moodlemobileapp' ) {
$local ++ ;
}
if ( $file == APPMODULENAME ) {
$local ++ ;
}
$success ++ ;
$success ++ ;
}
}
}
$percentage = floor ( $success / $total * 100 );
$bar = progressbar ( $percentage );
echo " Checking " . $title . str_repeat ( " \t " , 7 - floor ( mb_strlen ( $title , 'UTF-8' ) / 8 ));
echo " \t $success of $total -> $percentage % $bar ( $local local) " ;
if (( $percentage > 75 && $local > 50 ) || ( $percentage > 50 && $local > 75 )) {
echo " \t DETECTED \n " ;
return true ;
if ( $local == 0 ) {
echo " \t No Mobile App strings found \n " ;
} else {
$percentage = floor ( $success / $total * 100 );
$bar = progressbar ( $percentage );
echo " \t $success of $total -> $percentage % $bar ( $local local) " ;
if (( $percentage > 75 && $local > 50 ) || ( $percentage > 50 && $local > 75 )) {
echo " \t DETECTED \n " ;
return true ;
}
echo " \n " ;
}
echo " \n " ;
return false ;
}
/**
* Save a key - value pair into a json file .
*
* @ param key Key of the json object .
* @ param value Value of the json object .
* @ param filePath Path of the json file .
*/
function save_key ( $key , $value , $filePath ) {
$file = file_get_contents ( $filePath );
$file = ( array ) json_decode ( $file );
$file = load_json ( $filePath );
$value = html_entity_decode ( $value );
if ( ! isset ( $file [ $key ]) || $file [ $key ] != $value ) {
$file [ $key ] = $value ;
@ -378,7 +450,12 @@ function save_key($key, $value, $filePath) {
}
}
function override_component_lang_files ( $keys , $translations ) {
/**
* Take newer ENGLISH translations from the langpacks and applies it to the app lang . json files .
*
* @ param [ array ] $translations English translations .
*/
function override_component_lang_files ( $translations ) {
echo " Override component lang files. \n " ;
foreach ( $translations as $key => $value ) {
$path = '../src/' ;
@ -424,65 +501,40 @@ function override_component_lang_files($keys, $translations) {
}
/**
* Generates local mo o dle mobile app file to update languages in AMOS .
* Generates local mo du le file to update languages in AMOS .
*
* @ param [ array ] $ keys Translation keys .
* @ param [ array ] $translations English translations .
* @ param [ array ] $ appindex Translation appindex .
* @ param [ array ] $translations English translations .
*/
function generate_local_moodlemobileapp ( $keys , $translations ) {
echo " Generate local_moodlemobileapp. \n " ;
$string = ' < ? php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
function generate_local_module_file ( $appindex , $translations ) {
echo 'Generate ' . APPMODULENAME . " \n " ;
/**
* Version details .
*
* @ package local
* @ subpackage moodlemobileapp
* @ copyright 2014 Juan Leyva < juanleyvadelgado @ gmail . com >
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
*/
$string [ \ ' appstoredescription\ ' ] = \ ' NOTE : This official Moodle Mobile app will ONLY work with Moodle sites that have been set up to allow it . Please talk to your Moodle administrator if you have any problems connecting .
If your Moodle site has been configured correctly , you can use this app to :
- browse the content of your courses , even when offline
- receive instant notifications of messages and other events
- quickly find and contact other people in your courses
- upload images , audio , videos and other files from your mobile device
- view your course grades
- and more !
Please see http :// docs . moodle . org / en / Mobile_app for all the latest information .
We’ d really appreciate any good reviews about the functionality so far , and your suggestions on what else you want this app to do !
The app requires the following permissions :
Record audio - For recording audio to upload to Moodle
Read and modify the contents of your SD card - Contents are downloaded to the SD Card so you can see them offline
Network access - To be able to connect with your Moodle site and check if you are connected or not to switch to offline mode
Run at startup - So you receive local notifications even when the app is running in the background
Prevent phone from sleeping - So you can receive push notifications anytime\ ';' . " \n " ;
foreach ( $keys as $key => $value ) {
if ( isset ( $translations [ $key ]) && $value -> file == 'local_moodlemobileapp' ) {
$string .= '$string[\'' . $key . '\'] = \'' . str_replace ( " ' " , " \ ' " , $translations [ $key ]) . '\';' . " \n " ;
$lmsstring = " " ;
foreach ( $appindex as $appkey => $lmskey ) {
if ( isset ( $translations [ $appkey ])) {
$lmsstring .= '$string[\'' . $appkey . '\'] = \'' . str_replace ( " ' " , " \ ' " , $translations [ $appkey ]) . '\';' . " \n " ;
}
}
$string .= '$string[\'pluginname\'] = \'Moodle Mobile language strings\';' . " \n " ;
file_put_contents ( '../../moodle-local_moodlemobileapp/lang/en/local_moodlemobileapp.php' , $string . " \n " );
if ( empty ( $lmsstring )) {
echo " ERROR, translations not found, you probably didn't run gulp lang! \n " ;
return ;
}
$filepath = '../../moodle-' . APPMODULENAME . '/lang/en/' . APPMODULENAME . '.php' ;
$filecontents = file_get_contents ( $filepath );
$startcomment = " /* AUTO START */ \n " ;
$endcomment = '/* AUTO END */' ;
$start = strpos ( $filecontents , $startcomment );
$start = $start === false ? 0 : $start + strlen ( $startcomment );
$end = strpos ( $filecontents , $endcomment , $start );
$end = $end === false ? strlen ( $filecontents ) : $end ;
$filecontents = substr_replace ( $filecontents , $lmsstring , $start , $end - $start );
file_put_contents ( $filepath , $filecontents );
}