package Ġcom . github . gradle . android . i 1 8 n . import Ċ Ċ import Ġcom . github . gradle . android . i 1 8 n . conf . Configuration Ċ import Ġcom . github . gradle . android . i 1 8 n . model .* Ċ import Ġorg . apache . poi . ss . user model . Row Ċ import Ġorg . apache . poi . ss . user model . Sheet Ċ import Ġorg . apache . poi . ss . user model . Workbook Ċ import Ġorg . apache . poi . ss . user model . Workbook Factory Ċ import Ġorg . gradle . api . Project Ċ import Ġjava . io . File Ċ import Ġjava . io . InputStream Ċ import Ġjava . nio . file . Path Ċ import Ġjava . nio . file . Paths Ċ Ċ /** Ċ Ġ* ĠAndroid Ġi 1 8 n Ġresources Ġimporter Ġfrom Ġ`. xls ` Ġand Ġ`. xlsx ` Ġsources . Ċ Ġ*/ Ċ class ĠX ls Importer ( private Ġval Ġproject : ĠProject ) Ġ: ĠAbstract Importer ( project ) Ġ{ ĊĊĠĠĠ Ġoverride Ġfun Ġgenerate ( inputStream : ĠInputStream , Ġconfig : ĠImport Config ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġproject Data Ġ= ĠWork book Factory . create ( inputStream ). use Ġ{ Ġworkbook Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( project . is Single Module ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġworkbook . to Single Module Project Data ( config ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġworkbook . to Multi Module Project Data () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġstring Resources By Path Ġ= Ġproject Data . toString Resources By Path ( project . project Dir , Ġconfig ) ĊĠĠĠĠĠĠĠ Ġstring Resources By Path . write () ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun ĠProject . is Single Module (): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn Ġthis . child Projects . size Ġ<= Ġ 1 Ċ } Ċ Ċ private Ġfun ĠWork book . to Multi Module Project Data (): ĠProject Data Ġ{ ĊĠĠĠ Ġval Ġmodule DataList Ġ= Ġthis . map Ġ{ Ġsheet : ĠSheet Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġstring Data By Locale Ġ= Ġsheet . toList (). toString Data By Locale () ĊĠĠĠĠĠĠĠ Ġval Ġtranslation DataList Ġ= Ġstring Data By Locale . keys . map Ġ{ Ġlocale Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ ĠTranslation Data ( locale , Ġstring Data By Locale [ locale ] Ġas ĠList < String Data >) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠModule Data ( sheet . sheet Name , Ġtranslation DataList ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn ĠProject Data ( module DataList ) Ċ } Ċ Ċ private Ġfun ĠWork book . to Single Module Project Data ( config : ĠImport Config ): ĠProject Data Ġ{ ĊĠĠĠ Ġval Ġrows Ġ= Ġread Workbook Rows ( config , Ġthis ) ĊĠĠĠ Ġval Ġstring Data By Locale Ġ= Ġrows . toString Data By Locale () ĊĠĠĠ Ġval Ġtranslation DataList Ġ= Ġstring Data By Locale . keys . map Ġ{ Ġlocale Ġ-> ĊĠĠĠĠĠĠĠ ĠTranslation Data ( locale , Ġstring Data By Locale [ locale ] Ġas ĠList < String Data >) ĊĠĠĠ Ġ} ĊĠĠĠ Ġval Ġmodule Data Ġ= ĠModule Data ( Module Data . DEFAULT _ NAME , Ġtranslation DataList ) ĊĠĠĠ Ġreturn ĠProject Data ( listOf ( module Data )) Ċ } Ċ Ċ private Ġfun ĠList < Row >. toString Data By Locale (): ĠMap < String , ĠList < String Data >> Ġ{ ĊĊĠĠĠ Ġ// ĠReading Ġlocales Ġrow . ĊĠĠĠ Ġval Ġheader Row Ġ= Ġthis . first () ĊĠĠĠ Ġval Ġlocalized Columns Ġ= Ġread Locale By Col Index ( header Row ) ĊĊĠĠĠ Ġ// ĠReading Ġother Ġdata Ġrow . ĊĠĠĠ Ġval Ġstring Key Set Ġ= Ġmutable Set Of < String ?> () Ġ// ĠKeys Ġset Ġfacilit ating Ġduplicated Ġkey Ġcontrol . ĊĠĠĠ Ġval Ġstring Data By Locale Ġ= Ġmutable Map Of < String , ĠMutable List < String Data >>() ĊĠĠĠ Ġthis . drop ( 1 ) ĊĠĠĠĠĠĠĠ Ġ. filter Not Ġ{ Ġrow Ġ-> ĠisEmpty Workbook Row ( row ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġrow Ġ-> Ġpair Checked String Key With Row ( row ) Ġ} ĊĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġ( string Key , Ġrow ) Ġ-> Ġ// ĠRecord Ġtranslations Ġ( key , Ġtext ) Ġby Ġlocale ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! string Key Set . add ( string Key )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" D uplicated Ġkey Ġ`$ string Key ` Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" at Ġline Ġ${ row . row Num Ġ+ Ġ 1 } Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" in Ġsheet Ġ`${ row . sheet . sheet Name }` " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow . drop ( 1 ). forEach Ġ{ Ġcell Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġlocalized Columns [ cell . column Index ]?. let Ġ{ Ġlocale Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġtranslated Text Ġ= Ġcell . string CellValue ?. clean Up Translated Text () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstring Data Ġ= ĠString Data ( string Key , Ġtranslated Text ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstring DataList Ġ= Ġstring Data By Locale [ locale ] Ġ?: Ġmutable ListOf () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstring DataList . add ( string Data ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġstring Data By Locale [ locale ] Ġ= Ġstring DataList ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġstring Data By Locale Ċ } Ċ Ċ private Ġfun Ġpair Checked String Key With Row ( row : ĠRow ): ĠPair < String ?, ĠRow > Ġ{ ĊĠĠĠ Ġval Ġstring Key Ġ= Ġrow . getCell ( 0 )?. string CellValue ?. trim () ĊĠĠĠ Ġif Ġ( is Invalid Key ( string Key )) Ġ{ ĊĠĠĠĠĠĠĠ Ġthrow ĠIllegalArgumentException ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ" Invalid Ġtranslation Ġkey Ġ`$ string Key ` Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" at Ġrow Ġ${ row . row Num Ġ+ Ġ 1 } Ġ" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ" in Ġsheet Ġ`${ row . sheet . sheet Name }` " ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn ĠPair ( string Key , Ġrow ) Ċ } Ċ Ċ private Ġfun ĠisEmpty Workbook Row ( row : ĠRow ): ĠBoolean Ġ{ ĊĠĠĠ Ġreturn ĠisEmpty Row ( ĊĠĠĠĠĠĠĠ Ġrow . getCell ( 0 )?. string CellValue , ĊĠĠĠĠĠĠĠ Ġrow . drop ( 1 ). map Ġ{ Ġcell Ġ-> Ġcell ?. string CellValue Ġ} ĊĠĠĠ Ġ) Ċ } Ċ Ċ private Ġfun Ġread Locale By Col Index ( header Row : ĠRow ): ĠMap < Int , ĠString > Ġ{ ĊĠĠĠ Ġ// ĠMap Ġstoring Ġeach Ġlocale Ġto Ġits Ġcorresponding Ġcolumn Ġindex . ĊĠĠĠ Ġval Ġlocalized Columns Ġ= Ġmutable Map Of < Int , ĠString >() ĊĠĠĠ Ġheader Row . drop ( 1 ) ĊĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . string CellValue . isNotBlank () Ġ} ĊĠĠĠĠĠĠĠ Ġ. forEach Ġ{ Ġcell Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġlocale Ġ= Ġcell . string CellValue . trim () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlocalized Columns [ cell . column Index ] Ġ= Ġlocale ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġlocalized Columns Ċ } Ċ Ċ private Ġfun Ġread Workbook Rows ( config : ĠImport Config , Ġworkbook : ĠWork book ): ĠList < Row > Ġ{ ĊĊĠĠĠ Ġval Ġresult Ġ= Ġmutable ListOf < Row >() ĊĠĠĠ Ġworkbook . filter Indexed Ġ{ Ġsheet Index , Ġsheet : ĠSheet Ġ-> ĊĠĠĠĠĠĠĠ Ġ// ĠAll Ġsheets Ġmatching Ġname Ġregex . ĊĠĠĠĠĠĠĠ Ġconfig . all Sheet s Ġ&& Ġconfig . sheet Name Regex . matches ( sheet . sheet Name ) Ġ|| Ġsheet Index Ġ== Ġ 0 ĊĠĠĠ Ġ}. forEach Indexed Ġ{ Ġsheet Index , Ġsheet : ĠSheet Ġ-> ĊĠĠĠĠĠĠĠ Ġsheet . forEach Indexed Ġ{ ĠrowIndex , Ġrow Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠRead Ġfirst Ġrow Ġ( locales ) Ġonly Ġfor Ġfirst Ġsheet ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( sheet Index Ġ== Ġ 0 Ġ|| ĠrowIndex Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġresult . add ( row ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġresult Ċ } Ċ Ċ private Ġfun ĠProject Data . toString Resources By Path ( ĊĠĠĠ Ġbase Dir : ĠFile , ĊĠĠĠ Ġconfig : ĠImport Config Ċ ): ĠMap < Path , ĠString Resources > Ġ{ ĊĠĠĠ Ġval Ġis Multi Module Ġ= Ġthis . modules . size Ġ> Ġ 1 ĊĠĠĠ Ġreturn Ġthis . modules . map Ġ{ Ġmodule Data Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġmodule Base Dir Ġ= Ġif Ġ( is Multi Module ) ĠFile ( base Dir , Ġmodule Data . path Relative To Proj ()). path Ġelse Ġbase Dir . path ĊĠĠĠĠĠĠĠ Ġval Ġmodule Res Path Ġ= ĠPaths . get ( module Base Dir , Ġ" src ", Ġ" main ", Ġ" res ") ĊĠĠĠĠĠĠĠ ĠPair ( module Res Path , Ġmodule Data ) ĊĠĠĠ Ġ}. flatMap Ġ{ Ġ( res DirPath , Ġmodule Data ) Ġ-> ĊĠĠĠĠĠĠĠ Ġmodule Data . translations . map Ġ{ Ġtranslation Data Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvalues Path Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( translation Data . locale Ġ== Ġconfig . default Locale ) Ġ" values " ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ" values -${ translation Data . locale }" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstrings FileName Ġ= Ġif Ġ( is Multi Module ) Ġmodule Data . strings FileName () Ġelse Ġ" strings . xml " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstrings File Sub Path Ġ= ĠPaths . get ( values Path , Ġstrings FileName ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstrings File FullPath Ġ= Ġres DirPath . resolve ( strings File Sub Path ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġstring Resources Ġ= Ġtranslation Data . toString Resources ( config ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠPair ( strings File FullPath , Ġstring Resources ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ}. associate By ({ Ġit . first Ġ}) Ġ{ Ġit . second Ġ} Ċ } Ċ Ċ private Ġfun ĠModule Data . strings FileName (): ĠString Ġ= ĊĠĠĠ Ġ"${ this . name ĊĠĠĠĠĠĠĠ Ġ. replace ("^ [^ . ]* \\. ". to Regex (), Ġ"") ĊĠĠĠĠĠĠĠ Ġ. replace ('- ', Ġ'_ ') }_ strings . xml " Ċ Ċ private Ġfun ĠModule Data . path Relative To Proj (): ĠString Ġ= ĊĠĠĠ Ġthis . name . split (". "). join ToString ( File . separator ) Ċ Ċ private Ġfun ĠTranslation Data . toString Resources ( config : ĠImport Config ): ĠString Resources Ġ{ ĊĊĠĠĠ Ġval Ġstring DataList By Pl ural ity Ġ= Ġthis . string DataList . groupBy Ġ{ ĊĠĠĠĠĠĠĠ Ġit . name ?. contains ( QU ANT ITY _ SEPARATOR ) Ġ== Ġtrue ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġval Ġsingular String DataList Ġ= Ġstring DataList By Pl ural ity [ false ] ĊĠĠĠ Ġval Ġplural String DataList Ġ= Ġstring DataList By Pl ural ity [ true ] ĊĊĠĠĠ Ġreturn ĠString Resources ( ĊĠĠĠĠĠĠĠ Ġlocale , ĊĠĠĠĠĠĠĠ Ġlocale Ġ== Ġconfig . default Locale , ĊĠĠĠĠĠĠĠ Ġsingular String DataList ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . sorted By Ġ{ Ġ( name , Ġ_) Ġ-> Ġname Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . to Sing ular Xml Resource List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . to Mutable List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġmutable ListOf (), ĊĠĠĠĠĠĠĠ Ġplural String DataList ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . sorted By Ġ{ Ġ( name , Ġ_) Ġ-> Ġname Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . to Pl ural Xml Resources List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ? . to Mutable List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġmutable ListOf () ĊĠĠĠ Ġ) Ċ } Ċ Ċ private Ġfun ĠList < String Data >. to Pl ural Xml Resources List (): ĠList < Xml Resources > Ġ{ ĊĠĠĠ Ġval Ġgrouped By Pl ural Key Ġ= Ġgroup By Ġ{ Ġstring Data : ĠString Data Ġ-> ĊĠĠĠĠĠĠĠ Ġassert ( string Data . name ?. contains ( QU ANT ITY _ SEPARATOR ) Ġ== Ġtrue ) ĊĠĠĠĠĠĠĠ Ġstring Data . name ?. split ( QU ANT ITY _ SEPARATOR ) !!. first () ĊĠĠĠ Ġ} ĊĠĠĠ Ġreturn Ġgrouped By Pl ural Key . map Ġ{ Ġ( plural Name , Ġplural String DataList ) Ġ-> ĊĠĠĠĠĠĠĠ ĠXml Resources ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġplural Name , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġplural String DataList . map Ġ{ Ġstring Data Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġquantity Ġ= Ġstring Data . name ?. split ( QU ANT ITY _ SEPARATOR )?. get ( 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠXml Resource ( name Ġ= Ġnull , Ġquantity Ġ= Ġquantity , Ġtext Ġ= Ġstring Data . text ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. to Mutable List () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ċ } Ċ Ċ private Ġfun ĠList < String Data >. to Sing ular Xml Resource List (): ĠList < Xml Resource > Ġ= ĊĠĠĠ Ġmap Ġ{ Ġstring Data Ġ-> ĊĠĠĠĠĠĠĠ ĠXml Resource ( name Ġ= Ġstring Data . name , Ġtext Ġ= Ġstring Data . text ) ĊĠĠĠ Ġ}. sorted By Ġ{ Ġit . name Ġ} Ċ Ċ private Ġfun ĠMap < Path , ĠString Resources >. write () Ġ{ ĊĠĠĠ ĠforEach Ġ{ Ġ( path , Ġstring Resources ) Ġ-> ĊĠĠĠĠĠĠĠ Ġval Ġoutput Res File Ġ= Ġpath . to File () ĊĠĠĠĠĠĠĠ Ġoutput Res File . parent File . mkdir s () ĊĠĠĠĠĠĠĠ ĠConfiguration . xml Mapper . writeValue ( output Res File , Ġstring Resources ) ĊĠĠĠ Ġ} Ċ }