Shared cmake folder
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1283 lines
42 KiB

  1. #################################################
  2. #
  3. # (C) 2018-2020 Slávek Banko
  4. # slavek (DOT) banko (AT) axis.cz
  5. #
  6. # Improvements and feedback are welcome
  7. #
  8. # This file is released under GPL >= 2
  9. #
  10. #################################################
  11. ##### include essential TDE macros ##############
  12. set( MASTER_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" )
  13. include( TDEMacros )
  14. ##### verify required programs ##################
  15. if( NOT DEFINED TDE_PREFIX AND IS_DIRECTORY /opt/trinity )
  16. set( TDE_PREFIX "/opt/trinity" )
  17. else( )
  18. set( TDE_PREFIX "/usr" )
  19. endif( )
  20. if( NOT DEFINED KDE_XGETTEXT_EXECUTABLE )
  21. find_program( KDE_XGETTEXT_EXECUTABLE
  22. NAMES kde-xgettext
  23. HINTS "${TDE_PREFIX}/bin"
  24. )
  25. if( "${KDE_XGETTEXT_EXECUTABLE}" STREQUAL "KDE_XGETTEXT_EXECUTABLE-NOTFOUND" )
  26. tde_message_fatal( "kde-xgettext is required but not found" )
  27. endif( )
  28. endif( )
  29. if( NOT DEFINED XGETTEXT_EXECUTABLE )
  30. find_program( XGETTEXT_EXECUTABLE
  31. NAMES xgettext
  32. HINTS "${TDE_PREFIX}/bin"
  33. )
  34. if( "${XGETTEXT_EXECUTABLE}" STREQUAL "XGETTEXT_EXECUTABLE-NOTFOUND" )
  35. tde_message_fatal( "xgettext is required but not found" )
  36. endif( )
  37. endif( )
  38. if( NOT DEFINED MSGUNIQ_EXECUTABLE )
  39. find_program( MSGUNIQ_EXECUTABLE
  40. NAMES msguniq
  41. HINTS "${TDE_PREFIX}/bin"
  42. )
  43. if( "${MSGUNIQ_EXECUTABLE}" STREQUAL "MSGUNIQ_EXECUTABLE-NOTFOUND" )
  44. tde_message_fatal( "msguniq is required but not found" )
  45. endif( )
  46. endif( )
  47. if( NOT DEFINED MSGCAT_EXECUTABLE )
  48. find_program( MSGCAT_EXECUTABLE
  49. NAMES msgcat
  50. HINTS "${TDE_PREFIX}/bin"
  51. )
  52. if( "${MSGCAT_EXECUTABLE}" STREQUAL "MSGCAT_EXECUTABLE-NOTFOUND" )
  53. tde_message_fatal( "msgcat is required but not found" )
  54. endif( )
  55. endif( )
  56. if( NOT DEFINED PO4A_GETTEXTIZE_EXECUTABLE )
  57. find_program( PO4A_GETTEXTIZE_EXECUTABLE
  58. NAMES po4a-gettextize
  59. HINTS "${TDE_PREFIX}/bin"
  60. )
  61. if( "${PO4A_GETTEXTIZE_EXECUTABLE}" STREQUAL "PO4A_GETTEXTIZE_EXECUTABLE-NOTFOUND" )
  62. tde_message_fatal( "po4a-gettextize is required but not found" )
  63. endif( )
  64. execute_process(
  65. COMMAND ${PO4A_GETTEXTIZE_EXECUTABLE} --version
  66. OUTPUT_VARIABLE _po4a_version
  67. ERROR_VARIABLE _po4a_version
  68. )
  69. string( REGEX REPLACE "^po4a-gettextize[^\n]* ([^ ]*)\n.*" "\\1" _po4a_version ${_po4a_version} )
  70. if( "${_po4a_version}" VERSION_LESS "0.45" )
  71. tde_message_fatal( "po4a version >= 0.45 is required but found only ${_po4_version}" )
  72. endif( )
  73. endif( )
  74. if( NOT DEFINED TDE_COMMON_TEXTS_POT )
  75. get_filename_component( TDE_SOURCE_BASE "${CMAKE_CURRENT_SOURCE_DIR}" ABSOLUTE )
  76. while( (NOT EXISTS "${TDE_SOURCE_BASE}/tdelibs"
  77. OR NOT IS_DIRECTORY "${TDE_SOURCE_BASE}/tdelibs" )
  78. AND NOT "${TDE_SOURCE_BASE}" STREQUAL "/" )
  79. get_filename_component( TDE_SOURCE_BASE "${TDE_SOURCE_BASE}" PATH )
  80. endwhile( )
  81. find_file( TDE_COMMON_TEXTS_POT
  82. NAMES tde.pot
  83. HINTS "${TDE_SOURCE_BASE}/tdelibs" "${TDE_PREFIX}/include" "${TDE_PREFIX}/include/tde"
  84. )
  85. if( "${TDE_COMMON_TEXTS_POT}" STREQUAL "TDE_COMMON_TEXTS_POT-NOTFOUND" )
  86. tde_message_fatal( "translation template with common texts not found" )
  87. endif( )
  88. endif( )
  89. #################################################
  90. #####
  91. ##### tde_l10n_add_subdirectory
  92. #####
  93. ##### The function simulates the add_subdirectory() behavior, but
  94. ##### the CMakeL10n.txt file is used instead of CMakeLists.txt.
  95. #####
  96. function( tde_l10n_add_subdirectory _dir )
  97. set( CMAKE_CURRENT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/${_dir}" )
  98. set( CMAKE_CURRENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/${_dir}" )
  99. include( ${CMAKE_CURRENT_SOURCE_DIR}/CMakeL10n.txt )
  100. endfunction( )
  101. #################################################
  102. #####
  103. ##### tde_l10n_auto_add_subdirectories
  104. #####
  105. ##### The function is equivalent to tde_auto_add_subdirectories, but
  106. ##### the CMakeL10n.txt file is used instead of CMakeLists.txt.
  107. #####
  108. function( tde_l10n_auto_add_subdirectories )
  109. file( GLOB _dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${CMAKE_CURRENT_SOURCE_DIR}/*" )
  110. foreach( _dir ${_dirs} )
  111. if( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_dir}
  112. AND NOT ${_dir} STREQUAL ".svn"
  113. AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_dir}/CMakeL10n.txt )
  114. tde_l10n_add_subdirectory( ${_dir} )
  115. endif( )
  116. endforeach( )
  117. endfunction( )
  118. #################################################
  119. #####
  120. ##### tde_l10n_create_template
  121. #####
  122. ##### Macro is used to generate a translation template - POT file.
  123. #####
  124. ##### Syntax:
  125. ##### tde_l10n_create_template(
  126. ##### [CATALOG] file_name
  127. ##### [SOURCES source_spec [source_spec]]
  128. ##### [COMMENT tag]
  129. ##### [EXCLUDES regex [regex]]
  130. ##### [KEYWORDS keyword [keyword]]
  131. ##### [ATTRIBUTES attrib_spec [attrib_spec]]
  132. ##### [X-POT common_texts.pot]
  133. ##### [DESTINATION directory]
  134. ##### )
  135. #####
  136. ##### Where:
  137. ##### CATALOG determines the target file name (without pot suffix).
  138. ##### If the name ends with '/', a catalog of the same name
  139. ##### will be created in the specified directory.
  140. ##### SOURCES can be specified by several options:
  141. ##### a) Do not specify anything
  142. ##### - all usual source files will be automatically searched.
  143. ##### b) Enter the directory name - for example, '.' or 'src'
  144. ##### - all the usual source files in the specified directory
  145. ##### and subdirectories will be searched.
  146. ##### c) Enter the mask - for example '*.cpp'
  147. ##### - all files with the specified mask will be searched.
  148. ##### d) Specify the name of the individual file.
  149. ##### The methods from b) to d) can be combined.
  150. ##### EXCLUDES determines which files are to be excluded from processing
  151. ##### COMMENT determines additional comment to extract by xgettext.
  152. ##### KEYWORDS determines additional keywords for xgettext.
  153. ##### Use "-" if is needed to disable default keywords.
  154. ##### ATTRIBUTES determines files and specification for extractattr:
  155. ##### source_spec:element,attribute[,context][[:element,attribute[,context]]...]
  156. ##### X-POT entries from common_texts.pot are not extracted
  157. ##### By default, "tde.pot" is searched for and used.
  158. ##### Use "-" to skip this.
  159. ##### DESTINATION determines directory to save translation template.
  160. ##### The destination directory is determined as follows:
  161. ##### a) Directory is specified as an argument.
  162. ##### b) The variable POT_SOURCE_DIR is set.
  163. ##### c) There is a 'translations' directory.
  164. ##### d) There is a 'po' directory.
  165. #####
  166. ##### Note:
  167. ##### Editing the _files list inside foreach( ${_files} ) below in the
  168. ##### code is safe, because in CMake foreach parameters are evaluated
  169. ##### before the loop starts. Therefore, the changes in the list inside
  170. ##### the loop do not have an unwanted impact on the loop processing.
  171. #####
  172. macro( tde_l10n_create_template )
  173. unset( _catalog )
  174. unset( _sources )
  175. unset( _excludes )
  176. unset( _files )
  177. unset( _desktops )
  178. unset( _pots )
  179. unset( _dest )
  180. unset( _keywords_add )
  181. unset( _comment )
  182. unset( _attributes )
  183. unset( _exclude_pot )
  184. unset( _pot )
  185. unset( _directive )
  186. set( _var _catalog )
  187. set( _keywords_c_default "i18n" "i18n:1,2" "tr2i18n" "tr2i18n:1,2" "I18N_NOOP" "I18N_NOOP2" )
  188. set( _keywords_desktop_default
  189. "-" "Name" "GenericName" "Comment" "Keywords"
  190. "Description" "ExtraNames" "X-TDE-Submenu" )
  191. foreach( _arg ${ARGN} )
  192. # found directive "CATALOG"
  193. if( "+${_arg}" STREQUAL "+CATALOG" )
  194. unset( _catalog )
  195. set( _var _catalog )
  196. set( _directive 1 )
  197. endif( )
  198. # found directive "SOURCES"
  199. if( "+${_arg}" STREQUAL "+SOURCES" )
  200. unset( _sources )
  201. set( _var _sources )
  202. set( _directive 1 )
  203. endif( )
  204. # found directive "SOURCES_DESKTOP"
  205. if( "+${_arg}" STREQUAL "+SOURCES_DESKTOP" )
  206. unset( _desktops )
  207. set( _var _desktops )
  208. set( _directive 1 )
  209. endif( )
  210. # found directive "EXCLUDES"
  211. if( "+${_arg}" STREQUAL "+EXCLUDES" )
  212. unset( _excludes )
  213. set( _var _excludes )
  214. set( _directive 1 )
  215. endif( )
  216. # found directive "DESTINATION"
  217. if( "+${_arg}" STREQUAL "+DESTINATION" )
  218. unset( _dest )
  219. set( _var _dest )
  220. set( _directive 1 )
  221. endif( )
  222. # found directive "COMMENT"
  223. if( "+${_arg}" STREQUAL "+COMMENT" )
  224. unset( _comment )
  225. set( _var _comment )
  226. set( _directive 1 )
  227. endif( )
  228. # found directive "KEYWORDS"
  229. if( "+${_arg}" STREQUAL "+KEYWORDS" )
  230. unset( _keywords_add )
  231. set( _var _keywords_add )
  232. set( _directive 1 )
  233. endif( )
  234. # found directive "ATTRIBUTES"
  235. if( "+${_arg}" STREQUAL "+ATTRIBUTES" )
  236. unset( _attributes )
  237. set( _var _attributes )
  238. set( _directive 1 )
  239. endif( )
  240. # found directive "X-POT"
  241. if( "+${_arg}" STREQUAL "+X-POT" )
  242. unset( _exclude_pot )
  243. set( _var _exclude_pot )
  244. set( _directive 1 )
  245. endif( )
  246. # collect data
  247. if( _directive )
  248. unset( _directive )
  249. elseif( _var )
  250. list( APPEND ${_var} ${_arg} )
  251. endif( )
  252. endforeach( )
  253. # verify catalog
  254. if( NOT _catalog )
  255. tde_message_fatal( "the name of the translation catalog is not defined" )
  256. endif( )
  257. # determine the destination directory
  258. if( NOT _dest )
  259. if( POT_SOURCE_DIR )
  260. set( _dest ${POT_SOURCE_DIR} )
  261. elseif( EXISTS "${MASTER_SOURCE_DIR}/translations" )
  262. set( _dest "${MASTER_SOURCE_DIR}/translations/" )
  263. elseif( EXISTS "${MASTER_SOURCE_DIR}/po" )
  264. set( _dest "${MASTER_SOURCE_DIR}/po/" )
  265. else( )
  266. tde_message_fatal( "cannot determine destination directory" )
  267. endif( )
  268. endif( )
  269. if( ${_dest} MATCHES "[^/]$" )
  270. set( _dest "${_dest}/" )
  271. endif( )
  272. if( ${_dest} MATCHES "^[^/]" )
  273. set( _dest "${CMAKE_CURRENT_SOURCE_DIR}/${_dest}" )
  274. endif( )
  275. if( ${_catalog} MATCHES "/$" )
  276. string( REGEX REPLACE "/$" "" _catalog "${_catalog}" )
  277. get_filename_component( _catalog_base "${_catalog}" NAME )
  278. set( _catalog "${_catalog}/${_catalog_base}" )
  279. endif( )
  280. get_filename_component( _potFilename "${_dest}${_catalog}.pot" ABSOLUTE )
  281. file( RELATIVE_PATH _potFilename ${CMAKE_SOURCE_DIR} ${_potFilename} )
  282. message( STATUS "Create translation template ${_potFilename}" )
  283. # verify sources
  284. if( NOT _sources AND NOT _attributes AND NOT _desktops )
  285. # add current directory
  286. list( APPEND _sources "." )
  287. endif( )
  288. foreach( _src ${_sources} )
  289. # add all source files from directory
  290. if( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_src} )
  291. if( ${_src} STREQUAL "." )
  292. set( _dir "${CMAKE_CURRENT_SOURCE_DIR}" )
  293. else( )
  294. set( _dir "${CMAKE_CURRENT_SOURCE_DIR}/${_src}" )
  295. endif( )
  296. file( GLOB_RECURSE _add_files
  297. RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
  298. ${_dir}/*.c
  299. ${_dir}/*.cc
  300. ${_dir}/*.cpp
  301. ${_dir}/*.h
  302. ${_dir}/*.kcfg
  303. ${_dir}/*.rc
  304. ${_dir}/*.ui
  305. )
  306. list( SORT _add_files )
  307. list( APPEND _files ${_add_files} )
  308. # add files by the specified mask
  309. elseif( ${_src} MATCHES "(\\*|\\?)" )
  310. file( GLOB_RECURSE _add_files
  311. RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
  312. ${CMAKE_CURRENT_SOURCE_DIR}/${_src}
  313. )
  314. list( SORT _add_files )
  315. list( APPEND _files ${_add_files} )
  316. # add a individual file
  317. elseif( EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_src} )
  318. list( APPEND _files ${_src} )
  319. endif( )
  320. endforeach( )
  321. # filter files by excludes
  322. if( _excludes )
  323. foreach( _src ${_files} )
  324. foreach( _exclude ${_excludes} )
  325. if( ${_src} MATCHES ${_exclude} )
  326. list( REMOVE_ITEM _files ${_src} )
  327. endif( )
  328. endforeach( )
  329. endforeach( )
  330. endif( )
  331. if( NOT _files AND NOT _attributes AND NOT _desktops )
  332. tde_message_fatal( "no source files found" )
  333. endif( )
  334. # prepare x-pot
  335. if( NOT _exclude_pot )
  336. set( _exclude_pot "${TDE_COMMON_TEXTS_POT}" )
  337. endif( )
  338. if( "${_exclude_pot}" STREQUAL "-" )
  339. unset( _exclude_pot )
  340. else( )
  341. if( ${_exclude_pot} MATCHES "^[^/]" )
  342. set( _exclude_pot "${CMAKE_CURRENT_SOURCE_DIR}/${_exclude_pot}" )
  343. endif( )
  344. set( _exclude_pot "-x${_exclude_pot}" )
  345. endif( )
  346. # prepare comment
  347. if( NOT "${_comment}" STREQUAL "" )
  348. if( "${_comment}" STREQUAL "-" OR "${_comment}" STREQUAL "all" )
  349. set( _comment "-c" )
  350. else( )
  351. set( _comment "-c${_comment}" )
  352. endif( )
  353. endif( )
  354. # prepare keywords
  355. unset( _keywords_c )
  356. unset( _keywords_desktop )
  357. foreach( _keyword ${_keywords_c_default} ${_keywords_add} )
  358. if( "${_keyword}" STREQUAL "-" )
  359. unset( _keywords_c )
  360. unset( _keyword )
  361. endif( )
  362. list( APPEND _keywords_c "-k${_keyword}" )
  363. endforeach( )
  364. foreach( _keyword ${_keywords_desktop_default} ${_keywords_add} )
  365. if( "${_keyword}" STREQUAL "-" )
  366. unset( _keywords_desktop )
  367. unset( _keyword )
  368. endif( )
  369. if( _keyword )
  370. list( APPEND _keywords_desktop "${_keyword}" )
  371. endif( )
  372. endforeach( )
  373. # prepare resource files *.kcfg, *.rc and *.ui
  374. foreach( _src ${_files} )
  375. if( ${_src} MATCHES "\\.(kcfg|rc|ui)(\\.cmake)?$" )
  376. set( _src_index 0 )
  377. set( _src_l10n "${_src}.tde_l10n" )
  378. list( FIND _files "${_src_l10n}" _src_file_index )
  379. while( "${_src_file_index}" GREATER -1 )
  380. set( _src_l10n "${_src}.tde_l10n${_src_index}" )
  381. list( FIND _files "${_src_l10n}" _src_file_index )
  382. math( EXPR _src_index "${_src_index}+1" )
  383. endwhile( )
  384. tde_l10n_prepare_xml( SOURCE ${_src} TARGET ${_src_l10n} )
  385. list( REMOVE_ITEM _files ${_src} )
  386. list( APPEND _files "${_src_l10n}" )
  387. endif( )
  388. endforeach( )
  389. # prepare attributes
  390. if( _attributes )
  391. foreach( _attrib ${_attributes} )
  392. if( ${_attrib} MATCHES "^([^:]+):(.+)$" )
  393. string( REGEX REPLACE "^([^:]+):(.+)$" "\\1" _attrib_glob ${_attrib} )
  394. string( REGEX REPLACE "^([^:]+):(.+)$" "\\2" _attrib_spec ${_attrib} )
  395. file( GLOB_RECURSE _attrib_files
  396. RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
  397. ${CMAKE_CURRENT_SOURCE_DIR}/${_attrib_glob}
  398. )
  399. if( _excludes )
  400. foreach( _src ${_attrib_files} )
  401. foreach( _exclude ${_excludes} )
  402. if( ${_src} MATCHES ${_exclude} )
  403. list( REMOVE_ITEM _attrib_files ${_src} )
  404. endif( )
  405. endforeach( )
  406. endforeach( )
  407. endif( )
  408. if( _attrib_files )
  409. list( SORT _attrib_files )
  410. string( REGEX MATCHALL "[^:]+" _attrib_spec "${_attrib_spec}" )
  411. foreach( _src ${_attrib_files} )
  412. set( _src_index 0 )
  413. set( _src_l10n "${_src}.tde_l10n" )
  414. list( FIND _files "${_src_l10n}" _src_file_index )
  415. while( "${_src_file_index}" GREATER -1 )
  416. set( _src_l10n "${_src}.tde_l10n${_src_index}" )
  417. list( FIND _files "${_src_l10n}" _src_file_index )
  418. math( EXPR _src_index "${_src_index}+1" )
  419. endwhile( )
  420. tde_l10n_prepare_xmlattr(
  421. SOURCE ${_src}
  422. TARGET ${_src_l10n}
  423. ATTRIBUTES ${_attrib_spec}
  424. )
  425. list( APPEND _files "${_src_l10n}" )
  426. endforeach( )
  427. endif( )
  428. endif( )
  429. endforeach( )
  430. endif( )
  431. # prepare tips
  432. foreach( _src ${_files} )
  433. if( ${_src} MATCHES "(^|/)tips$" )
  434. tde_l10n_preparetips( ${_src} )
  435. list( REMOVE_ITEM _files ${_src} )
  436. list( APPEND _files "${_src}.tde_l10n" )
  437. endif( )
  438. endforeach( )
  439. # prepare documentation
  440. foreach( _src ${_files} )
  441. if( ${_src} MATCHES "\\.(ad|adoc|docbook|[1-8])(\\.cmake)?$" )
  442. if( ${_src} MATCHES "\\.(ad|adoc)(\\.cmake)?$" )
  443. set( _doc_format "asciidoc" )
  444. elseif( ${_src} MATCHES "\\.(docbook)(\\.cmake)?$" )
  445. set( _doc_format "docbook" )
  446. elseif( ${_src} MATCHES "\\.([1-8])(\\.cmake)?$" )
  447. set( _doc_format "man" )
  448. else( )
  449. set( _doc_format "text" )
  450. endif( )
  451. execute_process(
  452. COMMAND ${PO4A_GETTEXTIZE_EXECUTABLE}
  453. -f ${_doc_format} -m ${_src}
  454. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  455. OUTPUT_VARIABLE _potDoc
  456. )
  457. if( _potDoc )
  458. string( REPLACE "Content-Type: text/plain; charset=CHARSET" "Content-Type: text/plain; charset=UTF-8" _potDoc "${_potDoc}" )
  459. string( REPLACE "Content-Transfer-Encoding: ENCODING" "Content-Transfer-Encoding: 8bit" _potDoc "${_potDoc}" )
  460. file( WRITE ${CMAKE_CURRENT_SOURCE_DIR}/${_src}.tde_l10n "${_potDoc}" )
  461. list( APPEND _pots ${_src}.tde_l10n )
  462. endif( )
  463. list( REMOVE_ITEM _files ${_src} )
  464. endif( )
  465. endforeach( )
  466. # pick desktop files - *.desktop, *.directory, *.kcsrc, *.protocol, *.theme, *.themerc and eventsrc
  467. foreach( _src ${_files} )
  468. if( ${_src} MATCHES "\\.(desktop|directory|kcsrc|protocol|theme|themerc)(\\.cmake)?$"
  469. OR ${_src} MATCHES "(^|/)eventsrc(\\.cmake)?$" )
  470. list( APPEND _desktops ${_src} )
  471. list( REMOVE_ITEM _files ${_src} )
  472. endif( )
  473. endforeach( )
  474. # pick pot files *.pot
  475. foreach( _src ${_files} )
  476. if( ${_src} MATCHES "\\.pot(\\.cmake)?(\\.tde_l10n)?$" )
  477. list( APPEND _pots ${_src} )
  478. list( REMOVE_ITEM _files ${_src} )
  479. endif( )
  480. endforeach( )
  481. # add common translator info
  482. if( _files )
  483. list( FIND _excludes "_translatorinfo" _translatorinfo_index )
  484. if( "${_translatorinfo_index}" LESS 0 )
  485. set( _translatorinfo
  486. "i18n(\"NAME OF TRANSLATORS\", \"Your names\")\n"
  487. "i18n(\"EMAIL OF TRANSLATORS\", \"Your emails\")\n"
  488. )
  489. file( WRITE ${CMAKE_CURRENT_SOURCE_DIR}/_translatorinfo.tde_l10n ${_translatorinfo} )
  490. list( INSERT _files 0 "_translatorinfo.tde_l10n" )
  491. endif( )
  492. endif( )
  493. # create translation template
  494. if( _files )
  495. execute_process(
  496. COMMAND ${KDE_XGETTEXT_EXECUTABLE} --foreign-user -C
  497. ${_comment} ${_keywords_c} ${_exclude_pot} -o - ${_files}
  498. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  499. OUTPUT_VARIABLE _pot
  500. )
  501. # set charset and encoding headers
  502. if( _pot )
  503. string( REPLACE "Content-Type: text/plain; charset=CHARSET" "Content-Type: text/plain; charset=UTF-8" _pot "${_pot}" )
  504. string( REPLACE "Content-Transfer-Encoding: ENCODING" "Content-Transfer-Encoding: 8bit" _pot "${_pot}" )
  505. endif( )
  506. endif( )
  507. # process desktop files
  508. if( _desktops )
  509. # prepare desktop files
  510. foreach( _src ${_desktops} )
  511. tde_l10n_prepare_desktop( ${_src} KEYWORDS ${_keywords_desktop} )
  512. list( REMOVE_ITEM _desktops ${_src} )
  513. list( APPEND _desktops "${_src}.tde_l10n" )
  514. endforeach( )
  515. # create translation template for desktop files
  516. if( _pot )
  517. set( _withPotHeader "--omit-header" )
  518. else( )
  519. set( _withPotHeader "--foreign-user" )
  520. endif( )
  521. execute_process(
  522. COMMAND ${XGETTEXT_EXECUTABLE} ${_withPotHeader}
  523. --from-code=UTF-8 -C -c -ki18n -o - ${_desktops}
  524. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  525. OUTPUT_VARIABLE _potDesktop
  526. )
  527. # merge translation templates
  528. if( _potDesktop )
  529. if( _pot )
  530. file( WRITE ${CMAKE_CURRENT_SOURCE_DIR}/extracted-pot.tmp "${_pot}" )
  531. file( APPEND ${CMAKE_CURRENT_SOURCE_DIR}/extracted-pot.tmp "${_potDesktop}" )
  532. execute_process(
  533. COMMAND ${MSGUNIQ_EXECUTABLE} --use-first
  534. INPUT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/extracted-pot.tmp
  535. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  536. OUTPUT_VARIABLE _pot
  537. )
  538. file( REMOVE ${CMAKE_CURRENT_SOURCE_DIR}/extracted-pot.tmp )
  539. else( )
  540. set( _pot "${_potDesktop}" )
  541. # set charset and encoding headers
  542. string( REPLACE "Content-Type: text/plain; charset=CHARSET" "Content-Type: text/plain; charset=UTF-8" _pot "${_pot}" )
  543. string( REPLACE "Content-Transfer-Encoding: ENCODING" "Content-Transfer-Encoding: 8bit" _pot "${_pot}" )
  544. endif( )
  545. endif( )
  546. endif( )
  547. # merge additional pot files
  548. if( _pots )
  549. file( WRITE ${CMAKE_CURRENT_SOURCE_DIR}/extracted-pot.tmp "${_pot}" )
  550. execute_process(
  551. COMMAND ${MSGCAT_EXECUTABLE} --use-first extracted-pot.tmp ${_pots}
  552. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  553. OUTPUT_VARIABLE _pot
  554. )
  555. file( REMOVE ${CMAKE_CURRENT_SOURCE_DIR}/extracted-pot.tmp )
  556. # set charset and encoding headers
  557. string( REPLACE "Content-Type: text/plain; charset=CHARSET" "Content-Type: text/plain; charset=UTF-8" _pot "${_pot}" )
  558. string( REPLACE "Content-Transfer-Encoding: ENCODING" "Content-Transfer-Encoding: 8bit" _pot "${_pot}" )
  559. endif( )
  560. # finalize translation template
  561. if( _pot )
  562. # update references for resources to original files and line numbers
  563. list( FIND _files "extracted-rc.tde_l10n" _extractedRC_index )
  564. if( "${_extractedRC_index}" GREATER -1
  565. AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/extracted-rc.tde_l10n )
  566. file( READ "${CMAKE_CURRENT_SOURCE_DIR}/extracted-rc.tde_l10n" _extractedRC )
  567. string( REGEX REPLACE "[^\n]" "" _extractedRC_len "${_extractedRC}" )
  568. string( LENGTH "+${_extractedRC_len}" _extractedRC_len )
  569. set( _rcPos 0 )
  570. while( _rcPos LESS ${_extractedRC_len} )
  571. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\1" _rcLine "${_extractedRC}" )
  572. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\2" _extractedRC "${_extractedRC}" )
  573. math( EXPR _rcPos "${_rcPos}+1" )
  574. if( "${_rcLine}" MATCHES "^//i18n: file .* line [0-9]*$" )
  575. string( REGEX REPLACE "^//i18n: file (.*) line ([0-9]*)$" "\\1:\\2" _rcOrig ${_rcLine} )
  576. endif( )
  577. if( "${_rcLine}" MATCHES "^i18n\\(" AND _rcOrig )
  578. string( REGEX REPLACE "(^|\n)(#:.*) extracted-rc.tde_l10n:${_rcPos}( |\n)" "\\1\\2 ${_rcOrig}\\3" _pot "${_pot}" )
  579. unset( _rcOrig )
  580. endif( )
  581. endwhile( )
  582. endif( )
  583. # update references for modified source files (".tde_l10n" extension)
  584. string( REGEX REPLACE "\\.tde_l10n[0-9]*(:[0-9]+)" "\\1" _pot "${_pot}" )
  585. # replace the references for _translatorinfo with instructions in the comment
  586. string( REGEX REPLACE
  587. "(^|\n)(#:[^\n]*) _translatorinfo:1($|[^\n]*)"
  588. "\\1#. Instead of a literal translation, add your name to the end of the list (separated by a comma).\n\\2\\3\n#, ignore-inconsistent"
  589. _pot "${_pot}"
  590. )
  591. string( REGEX REPLACE
  592. "(^|\n)(#:[^\n]*) _translatorinfo:2($|[^\n]*)"
  593. "\\1#. Instead of a literal translation, add your email to the end of the list (separated by a comma).\n\\2\\3\n#, ignore-inconsistent"
  594. _pot "${_pot}"
  595. )
  596. string( REGEX REPLACE "(^|\n)#:($|\n)" "\\1" _pot "${_pot}" )
  597. # save translation template
  598. if( EXISTS "${_dest}${_catalog}.pot" )
  599. file( READ "${_dest}${_catalog}.pot" _potOrig )
  600. else( )
  601. unset( _potOrig )
  602. endif( )
  603. if( _potOrig )
  604. string( REGEX REPLACE "\n\"POT-Creation-Date: [^\"]*\"\n" "" _potOrig "${_potOrig}" )
  605. string( REGEX REPLACE "\n\"POT-Creation-Date: [^\"]*\"\n" "" _potNew "${_pot}" )
  606. endif( )
  607. if( NOT _potOrig OR NOT "${_potNew}" STREQUAL "${_potOrig}" )
  608. file( WRITE "${_dest}${_catalog}.pot" "${_pot}" )
  609. endif( )
  610. endif( _pot )
  611. # cleanup
  612. foreach( _file ${_files} ${_desktops} ${_pots} )
  613. if( "${_file}" MATCHES "\\.tde_l10n[0-9]*$" )
  614. file( REMOVE ${CMAKE_CURRENT_SOURCE_DIR}/${_file} )
  615. endif( )
  616. endforeach( )
  617. endmacro( )
  618. #################################################
  619. #####
  620. ##### tde_l10n_preparetips
  621. #####
  622. ##### Macro is used to prepare tips file for xgettext
  623. #####
  624. macro( tde_l10n_preparetips _tips )
  625. tde_l10n_prepare_xml(
  626. SOURCE ${_tips}
  627. TAGS html
  628. C_FORMAT
  629. PRESERVE entities line-wrap spaces-leading spaces-trailing spaces-multi
  630. )
  631. endmacro( )
  632. #################################################
  633. #####
  634. ##### tde_l10n_prepare_xml
  635. #####
  636. ##### The function is used to prepare XML file for xgettext.
  637. ##### The default settings are identical to extractrc.
  638. #####
  639. function( tde_l10n_prepare_xml )
  640. unset( _source )
  641. unset( _target )
  642. unset( _context )
  643. set( _skip_properties "database|associations|populationText" )
  644. set( _tags "[tT][eE][xX][tT]|title|string|whatsthis|tooltip|label" )
  645. set( _preserve "line-wrap" "lines-leading" "lines-multi" "spaces-leading" "spaces-trailing" "spaces-multi" )
  646. set( _no_c_format 1 )
  647. unset( _directive )
  648. set( _var _source )
  649. foreach( _arg ${ARGN} )
  650. # found directive "SOURCE"
  651. if( "+${_arg}" STREQUAL "+SOURCE" )
  652. unset( _source )
  653. set( _var _source )
  654. set( _directive 1 )
  655. endif( )
  656. # found directive "TARGET"
  657. if( "+${_arg}" STREQUAL "+TARGET" )
  658. unset( _target )
  659. set( _var _target )
  660. set( _directive 1 )
  661. endif( )
  662. # found directive "CONTEXT"
  663. if( "+${_arg}" STREQUAL "+CONTEXT" )
  664. unset( _context )
  665. set( _var _context )
  666. set( _directive 1 )
  667. endif( )
  668. # found directive "SKIP-PROPERTIES"
  669. if( "+${_arg}" STREQUAL "+SKIP-PROPERTIES" )
  670. unset( _skip_properties )
  671. set( _var _skip_properties )
  672. set( _directive 1 )
  673. endif( )
  674. # found directive "TAGS"
  675. if( "+${_arg}" STREQUAL "+TAGS" )
  676. unset( _tags )
  677. set( _var _tags )
  678. set( _directive 1 )
  679. endif( )
  680. # found directive "PRESERVE"
  681. if( "+${_arg}" STREQUAL "+PRESERVE" )
  682. unset( _preserve )
  683. set( _var _preserve )
  684. set( _directive 1 )
  685. endif( )
  686. # found directive "C_FORMAT"
  687. if( "+${_arg}" STREQUAL "+C_FORMAT" )
  688. unset( _no_c_format )
  689. set( _directive 1 )
  690. endif( )
  691. # found directive "NO_C_FORMAT"
  692. if( "+${_arg}" STREQUAL "+NO_C_FORMAT" )
  693. set( _no_c_format 1 )
  694. set( _directive 1 )
  695. endif( )
  696. # collect data
  697. if( _directive )
  698. unset( _directive )
  699. elseif( _var )
  700. list( APPEND ${_var} ${_arg} )
  701. endif( )
  702. endforeach( )
  703. # verify source
  704. if( NOT _source )
  705. tde_message_fatal( "no source XML file" )
  706. endif( )
  707. if( NOT IS_ABSOLUTE "${_source}" )
  708. set( _source "${CMAKE_CURRENT_SOURCE_DIR}/${_source}" )
  709. endif( )
  710. if( NOT _target )
  711. set( _target "${_source}.tde_l10n" )
  712. endif( )
  713. if( NOT IS_ABSOLUTE "${_target}" )
  714. set( _target "${CMAKE_CURRENT_SOURCE_DIR}/${_target}" )
  715. endif( )
  716. # prepare tags to regexp
  717. string( REPLACE ";" "|" _tags "${_tags}" )
  718. if( "${_skip_properties}" STREQUAL "-" )
  719. unset( _skip_properties )
  720. endif( )
  721. if( DEFINED _skip_properties )
  722. string( REPLACE ";" "|" _skip_properties "${_skip_properties}" )
  723. set( _tags "property|${_tags}" )
  724. endif( )
  725. # read file
  726. file( READ ${_source} _xml_data )
  727. string( REGEX REPLACE "[^\n]" "" _xml_len ${_xml_data} )
  728. string( LENGTH "+${_xml_len}" _xml_len )
  729. # process lines
  730. set( _xml_pos 0 )
  731. unset( _xml_l10n )
  732. unset( _xml_inside )
  733. unset( _xml_tag_empty )
  734. unset( _xml_skipped_prop )
  735. while( _xml_pos LESS ${_xml_len} )
  736. # pick line
  737. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\1" _xml_line "${_xml_data}" )
  738. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\2" _xml_data "${_xml_data}" )
  739. math( EXPR _xml_pos "${_xml_pos}+1" )
  740. set( _xml_newline 1 )
  741. # process tags on line
  742. while( _xml_newline OR NOT "${_xml_line}" STREQUAL "" )
  743. unset( _xml_newline )
  744. unset( _xml_line_prefix )
  745. unset( _xml_line_suffix )
  746. unset( _xml_line_rest )
  747. if( NOT _xml_inside )
  748. if( _xml_skipped_prop AND "${_xml_line}" MATCHES "</property>" )
  749. unset( _xml_skipped_prop )
  750. string( REGEX MATCH "</property>(.*)" _xml_line "${_xml_line}" )
  751. string( REGEX REPLACE "^</property>(.*)" "\\1" _xml_line "${_xml_line}" )
  752. endif( )
  753. if( NOT _xml_skipped_prop AND "${_xml_line}" MATCHES "<(${_tags})([ \t][^>]*)*>" )
  754. string( REGEX MATCH "<(${_tags})([ \t][^>]*)*>(.*)" _xml_line "${_xml_line}" )
  755. string( REGEX MATCH "^<(${_tags})([ \t][^>]*)*>" _xml_attr "${_xml_line}" )
  756. string( REGEX REPLACE "^<(${_tags})([ \t][^>]*)*>(.*)" "\\3" _xml_line "${_xml_line}" )
  757. if( "${_xml_attr}" MATCHES "^<property([ \t][^>]*)*>" AND DEFINED _skip_properties )
  758. if( "${_xml_attr}" MATCHES "[ \t]name=\"(${_skip_properties})\"" )
  759. set( _xml_skipped_prop 1 )
  760. endif( )
  761. set( _xml_line_rest "${_xml_line}" )
  762. set( _xml_line "" )
  763. else( )
  764. set( _xml_inside 1 )
  765. set( _xml_context "${_context}" )
  766. if( "${_xml_attr}" MATCHES "[ \t]context=\"([^\"]*)\"" )
  767. string( REGEX REPLACE ".* context=\"([^\"]*)\".*" "\\1" _xml_context "${_xml_attr}" )
  768. endif( )
  769. set( _xml_line_prefix "i18n(" )
  770. if( _no_c_format )
  771. set( _xml_line_prefix "${_xml_line_prefix}/* xgettext: no-c-format */" )
  772. endif( )
  773. if( _xml_context )
  774. set( _xml_line_prefix "${_xml_line_prefix}\"${_xml_context}\", " )
  775. endif( )
  776. set( _xml_tag_empty 1 )
  777. endif( )
  778. else( )
  779. set( _xml_line "" )
  780. endif( )
  781. endif( )
  782. if( _xml_inside )
  783. if( "${_xml_line}" MATCHES "</(${_tags})>" )
  784. unset( _xml_inside )
  785. string( REGEX REPLACE "</(${_tags})>(.*)" "\\2" _xml_line_rest "${_xml_line}" )
  786. string( REGEX REPLACE "</(${_tags})>(.*)" "" _xml_line "${_xml_line}" )
  787. set( _xml_line_suffix ");" )
  788. endif( )
  789. string( REGEX REPLACE "\\\\" "\\\\\\\\" _xml_line "${_xml_line}" )
  790. string( REGEX REPLACE "\\\"" "\\\\\"" _xml_line "${_xml_line}" )
  791. string( REGEX REPLACE "\t" "\\\\t" _xml_line "${_xml_line}" )
  792. if( NOT ";${_preserve};" MATCHES ";entities;" )
  793. string( REGEX REPLACE "&lt;" "<" _xml_line "${_xml_line}" )
  794. string( REGEX REPLACE "&gt;" ">" _xml_line "${_xml_line}" )
  795. string( REGEX REPLACE "&amp;" "&" _xml_line "${_xml_line}" )
  796. endif( )
  797. if( NOT ";${_preserve};" MATCHES ";spaces-leading;" )
  798. string( REGEX REPLACE "^ +" "" _xml_line "${_xml_line}" )
  799. endif( )
  800. if( NOT ";${_preserve};" MATCHES ";spaces-trailing;" )
  801. string( REGEX REPLACE " +$" "" _xml_line "${_xml_line}" )
  802. endif( )
  803. if( NOT ";${_preserve};" MATCHES ";spaces-multi;" )
  804. string( REGEX REPLACE " +" " " _xml_line "${_xml_line}" )
  805. endif( )
  806. if( _xml_inside )
  807. if( ";${_preserve};" MATCHES ";line-wrap;" )
  808. if( NOT "${_xml_line}" STREQUAL ""
  809. OR ( ";${_preserve};" MATCHES ";lines-leading;" AND _xml_tag_empty )
  810. OR ( ";${_preserve};" MATCHES ";lines-multi;" AND NOT _xml_tag_empty ) )
  811. set( _xml_line "${_xml_line}\\n" )
  812. endif( )
  813. elseif( NOT "${_xml_line}" STREQUAL "" AND NOT _xml_tag_empty )
  814. set( _xml_line " ${_xml_line}" )
  815. endif( )
  816. endif( )
  817. if( NOT "${_xml_line}" STREQUAL "" )
  818. unset( _xml_tag_empty )
  819. endif( )
  820. endif( )
  821. # drop empty tag on single line
  822. if( _xml_line_prefix AND _xml_line_suffix AND _xml_tag_empty )
  823. # skip empty string for translation
  824. # add current tag to output
  825. else( )
  826. set( _xml_l10n "${_xml_l10n}${_xml_line_prefix}" )
  827. if( NOT "${_xml_line}" STREQUAL "" OR ( _xml_line_suffix AND _xml_tag_empty ) )
  828. set( _xml_l10n "${_xml_l10n}\"${_xml_line}\"" )
  829. endif( )
  830. set( _xml_l10n "${_xml_l10n}${_xml_line_suffix}" )
  831. endif( )
  832. # take the rest of the line for processing
  833. set( _xml_line "${_xml_line_rest}" )
  834. endwhile( )
  835. set( _xml_l10n "${_xml_l10n}\n" )
  836. endwhile( )
  837. # write file
  838. file( WRITE ${_target} "${_xml_l10n}" )
  839. endfunction( )
  840. #################################################
  841. #####
  842. ##### tde_l10n_prepare_xmlattr
  843. #####
  844. ##### The function is used to prepare attributes in XML file
  845. ##### for xgettext, comparable to extractattr.
  846. #####
  847. function( tde_l10n_prepare_xmlattr )
  848. unset( _source )
  849. unset( _target )
  850. unset( _context )
  851. unset( _attribs )
  852. unset( _directive )
  853. set( _preserve "line-wrap" "lines-leading" "spaces-leading" "spaces-trailing" "spaces-multi" )
  854. set( _var _source )
  855. foreach( _arg ${ARGN} )
  856. # found directive "SOURCE"
  857. if( "+${_arg}" STREQUAL "+SOURCE" )
  858. unset( _source )
  859. set( _var _source )
  860. set( _directive 1 )
  861. endif( )
  862. # found directive "TARGET"
  863. if( "+${_arg}" STREQUAL "+TARGET" )
  864. unset( _target )
  865. set( _var _target )
  866. set( _directive 1 )
  867. endif( )
  868. # found directive "CONTEXT"
  869. if( "+${_arg}" STREQUAL "+CONTEXT" )
  870. unset( _context )
  871. set( _var _context )
  872. set( _directive 1 )
  873. endif( )
  874. # found directive "ATTRIBUTES"
  875. if( "+${_arg}" STREQUAL "+ATTRIBUTES" )
  876. unset( _attribs )
  877. set( _var _attribs )
  878. set( _directive 1 )
  879. endif( )
  880. # found directive "PRESERVE"
  881. if( "+${_arg}" STREQUAL "+PRESERVE" )
  882. unset( _preserve )
  883. set( _var _preserve )
  884. set( _directive 1 )
  885. endif( )
  886. # collect data
  887. if( _directive )
  888. unset( _directive )
  889. elseif( _var )
  890. list( APPEND ${_var} ${_arg} )
  891. endif( )
  892. endforeach( )
  893. # verify source
  894. if( NOT _source )
  895. tde_message_fatal( "no source XML file" )
  896. endif( )
  897. if( NOT IS_ABSOLUTE "${_source}" )
  898. set( _source "${CMAKE_CURRENT_SOURCE_DIR}/${_source}" )
  899. endif( )
  900. if( NOT _target )
  901. set( _target "${_source}.tde_l10n" )
  902. endif( )
  903. if( NOT IS_ABSOLUTE "${_target}" )
  904. set( _target "${CMAKE_CURRENT_SOURCE_DIR}/${_target}" )
  905. endif( )
  906. # prepare tags to regexp
  907. if( NOT _attribs )
  908. tde_message_fatal( "no attributes specified" )
  909. endif( )
  910. unset( _tags )
  911. foreach( _attrib ${_attribs} )
  912. string( REGEX REPLACE "^([^,]+),.*" "\\1" _tag "${_attrib}" )
  913. list( APPEND _tags "${_tag}" )
  914. endforeach( )
  915. list( REMOVE_DUPLICATES _tags )
  916. string( REPLACE ";" "|" _tags "${_tags}" )
  917. # read file
  918. file( READ ${_source} _xml_data )
  919. string( REGEX REPLACE "[^\n]" "" _xml_len ${_xml_data} )
  920. string( LENGTH "+${_xml_len}" _xml_len )
  921. # process lines
  922. set( _xml_pos 0 )
  923. unset( _xml_l10n )
  924. unset( _xml_inside_tag )
  925. unset( _xml_inside_attrib )
  926. unset( _xml_attrib_empty )
  927. while( _xml_pos LESS ${_xml_len} )
  928. # pick line
  929. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\1" _xml_line "${_xml_data}" )
  930. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\2" _xml_data "${_xml_data}" )
  931. math( EXPR _xml_pos "${_xml_pos}+1" )
  932. set( _xml_newline 1 )
  933. # process tags on line
  934. while( _xml_newline OR NOT "${_xml_line}" STREQUAL "" )
  935. unset( _xml_line_rest )
  936. if( NOT _xml_inside_tag )
  937. if( "${_xml_line}" MATCHES "<(${_tags})([ \t\n][^>]*|$)" )
  938. set( _xml_inside_tag 1 )
  939. string( REGEX MATCH "<(${_tags})([ \t\n][^>]*|$)(.*)" _xml_line "${_xml_line}" )
  940. string( REGEX REPLACE "^<(${_tags})[ \t\n]*.*" "\\1" _xml_tag "${_xml_line}" )
  941. string( REGEX REPLACE "^<(${_tags})[ \t\n]*" "" _xml_line "${_xml_line}" )
  942. unset( _tag_attribs )
  943. foreach( _attrib ${_attribs} )
  944. if( "${_attrib}" MATCHES "^${_xml_tag}," )
  945. string( REGEX REPLACE "^([^,]+),([^,]+),?(.*)" "\\2" _attrib "${_attrib}" )
  946. list( APPEND _tag_attribs "${_attrib}" )
  947. endif( )
  948. endforeach( )
  949. string( REPLACE ";" "|" _tag_attribs "${_tag_attribs}" )
  950. unset( _xml_inside_attrib )
  951. else( )
  952. set( _xml_line "" )
  953. endif( )
  954. endif( )
  955. if( _xml_inside_tag )
  956. if( "${_xml_line}" MATCHES "^(([ \t]*[^>=]+=\"[^\"]*\")*)[ \t]*/?>" )
  957. unset( _xml_inside_tag )
  958. string( REGEX REPLACE "^(([ \t]*[^>=]+=\"[^\"]*\")*)[ \t]*/?>(.*)" "\\3" _xml_line_rest "${_xml_line}" )
  959. string( REGEX REPLACE "^(([ \t]*[^>=]+=\"[^\"]*\")*)[ \t]*/?>(.*)" "\\1" _xml_line "${_xml_line}" )
  960. endif( )
  961. # process attribs on line
  962. set( _xml_attrib_line "${_xml_line}" )
  963. while( _xml_newline OR NOT "${_xml_attrib_line}" STREQUAL "" )
  964. unset( _xml_newline )
  965. unset( _xml_line_prefix )
  966. unset( _xml_line_suffix )
  967. unset( _xml_attrib_line_rest )
  968. if( NOT _xml_inside_attrib )
  969. if( "${_xml_attrib_line}" MATCHES "(^|[ \t]+)(${_tag_attribs})=\"" )
  970. set( _xml_inside_attrib 1 )
  971. string( REGEX MATCH "(^|[ \t]+)(${_tag_attribs})=\"(.*)" _xml_attrib_line "${_xml_attrib_line}" )
  972. string( REGEX REPLACE "^[ \t]*(${_tag_attribs})=\".*" "\\1" _xml_attrib "${_xml_attrib_line}" )
  973. string( REGEX REPLACE "^[ \t]*(${_tag_attribs})=\"" "" _xml_attrib_line "${_xml_attrib_line}" )
  974. set( _xml_context "${_context}" )
  975. foreach( _attrib ${_attribs} )
  976. if( "${_attrib}" MATCHES "^${_xml_tag},${_xml_attrib}," )
  977. string( REGEX REPLACE "^([^,]+),([^,]+),?(.*)" "\\3" _xml_context "${_attrib}" )
  978. endif( )
  979. endforeach( )
  980. set( _xml_line_prefix "i18n(" )
  981. if( _xml_context )
  982. set( _xml_line_prefix "${_xml_line_prefix}\"${_xml_context}\", " )
  983. endif( )
  984. set( _xml_attrib_empty 1 )
  985. else( )
  986. set( _xml_attrib_line "" )
  987. endif( )
  988. endif( )
  989. if( _xml_inside_attrib )
  990. if( "${_xml_attrib_line}" MATCHES "\"" )
  991. unset( _xml_inside_attrib )
  992. string( REGEX REPLACE "\"(.*)" "\\1" _xml_attrib_line_rest "${_xml_attrib_line}" )
  993. string( REGEX REPLACE "\"(.*)" "" _xml_attrib_line "${_xml_attrib_line}" )
  994. set( _xml_line_suffix ");" )
  995. endif( )
  996. string( REGEX REPLACE "\\\\" "\\\\\\\\" _xml_attrib_line "${_xml_attrib_line}" )
  997. string( REGEX REPLACE "\\\"" "\\\\\"" _xml_attrib_line "${_xml_attrib_line}" )
  998. string( REGEX REPLACE "\t" "\\\\t" _xml_attrib_line "${_xml_attrib_line}" )
  999. if( NOT ";${_preserve};" MATCHES ";entities;" )
  1000. string( REGEX REPLACE "&lt;" "<" _xml_attrib_line "${_xml_attrib_line}" )
  1001. string( REGEX REPLACE "&gt;" ">" _xml_attrib_line "${_xml_attrib_line}" )
  1002. string( REGEX REPLACE "&amp;" "&" _xml_attrib_line "${_xml_attrib_line}" )
  1003. endif( )
  1004. if( NOT ";${_preserve};" MATCHES ";spaces-leading;" )
  1005. string( REGEX REPLACE "^ +" "" _xml_attrib_line "${_xml_attrib_line}" )
  1006. endif( )
  1007. if( NOT ";${_preserve};" MATCHES ";spaces-trailing;" )
  1008. string( REGEX REPLACE " +$" "" _xml_attrib_line "${_xml_attrib_line}" )
  1009. endif( )
  1010. if( NOT ";${_preserve};" MATCHES ";spaces-multi;" )
  1011. string( REGEX REPLACE " +" " " _xml_attrib_line "${_xml_attrib_line}" )
  1012. endif( )
  1013. if( NOT "${_xml_inside_attrib}" STREQUAL "" )
  1014. if( ";${_preserve};" MATCHES ";line-wrap;" )
  1015. if( ";${_preserve};" MATCHES ";lines-leading;"
  1016. OR NOT "${_xml_attrib_line}" STREQUAL "" OR NOT _xml_attrib_empty )
  1017. set( _xml_attrib_line "${_xml_attrib_line}\\n" )
  1018. endif( )
  1019. elseif( NOT "${_xml_attrib_line}" STREQUAL "" AND NOT _xml_attrib_empty )
  1020. set( _xml_attrib_line " ${_xml_attrib_line}" )
  1021. endif( )
  1022. endif( )
  1023. if( NOT "${_xml_attrib_line}" STREQUAL "" )
  1024. unset( _xml_attrib_empty )
  1025. endif( )
  1026. endif( )
  1027. # drop empty attrib on single line
  1028. if( _xml_line_prefix AND _xml_line_suffix AND _xml_attrib_empty )
  1029. # skip empty translation
  1030. # add current attrib to output
  1031. else( )
  1032. set( _xml_l10n "${_xml_l10n}${_xml_line_prefix}" )
  1033. if( NOT "${_xml_attrib_line}" STREQUAL "" OR ( _xml_line_suffix AND _xml_attrib_empty ) )
  1034. set( _xml_l10n "${_xml_l10n}\"${_xml_attrib_line}\"" )
  1035. endif( )
  1036. set( _xml_l10n "${_xml_l10n}${_xml_line_suffix}" )
  1037. endif( )
  1038. # take the rest of the line for processing
  1039. set( _xml_attrib_line "${_xml_attrib_line_rest}" )
  1040. endwhile( )
  1041. endif( )
  1042. # take the rest of the line for processing
  1043. unset( _xml_newline )
  1044. set( _xml_line "${_xml_line_rest}" )
  1045. endwhile( )
  1046. set( _xml_l10n "${_xml_l10n}\n" )
  1047. endwhile( )
  1048. # write file
  1049. file( WRITE ${_target} "${_xml_l10n}" )
  1050. endfunction( )
  1051. #################################################
  1052. #####
  1053. ##### tde_l10n_prepare_desktop
  1054. #####
  1055. ##### The function is used to prepare desktop style file
  1056. ##### for xgettext.
  1057. #####
  1058. ##### Note: gettext >= 0.19 includes support for extracting
  1059. ##### strings from desktop files, but there are some drawbacks.
  1060. #####
  1061. function( tde_l10n_prepare_desktop )
  1062. unset( _source )
  1063. unset( _target )
  1064. unset( _keywords )
  1065. unset( _directive )
  1066. set( _var _source )
  1067. foreach( _arg ${ARGN} )
  1068. # found directive "SOURCE"
  1069. if( "+${_arg}" STREQUAL "+SOURCE" )
  1070. unset( _source )
  1071. set( _var _source )
  1072. set( _directive 1 )
  1073. endif( )
  1074. # found directive "TARGET"
  1075. if( "+${_arg}" STREQUAL "+TARGET" )
  1076. unset( _target )
  1077. set( _var _target )
  1078. set( _directive 1 )
  1079. endif( )
  1080. # found directive "KEYWORDS"
  1081. if( "+${_arg}" STREQUAL "+KEYWORDS" )
  1082. unset( _keywords )
  1083. set( _var _keywords )
  1084. set( _directive 1 )
  1085. endif( )
  1086. # collect data
  1087. if( _directive )
  1088. unset( _directive )
  1089. elseif( _var )
  1090. list( APPEND ${_var} ${_arg} )
  1091. endif( )
  1092. endforeach( )
  1093. # verify source
  1094. if( NOT _source )
  1095. tde_message_fatal( "no source desktop file" )
  1096. endif( )
  1097. if( NOT IS_ABSOLUTE "${_source}" )
  1098. set( _source "${CMAKE_CURRENT_SOURCE_DIR}/${_source}" )
  1099. endif( )
  1100. if( NOT _target )
  1101. set( _target "${_source}.tde_l10n" )
  1102. endif( )
  1103. if( NOT IS_ABSOLUTE "${_target}" )
  1104. set( _target "${CMAKE_CURRENT_SOURCE_DIR}/${_target}" )
  1105. endif( )
  1106. # prepare keywords
  1107. if( NOT _keywords )
  1108. tde_message_fatal( "the keywords whose strings are to be extracted are not specified" )
  1109. endif( )
  1110. string( REPLACE ";" "|" _keywords_match "(${_keywords})" )
  1111. # read file
  1112. file( READ ${_source} _desktop_data )
  1113. string( REGEX REPLACE "[^\n]" "" _desktop_len ${_desktop_data} )
  1114. string( LENGTH "+${_desktop_len}" _desktop_len )
  1115. # process lines
  1116. set( _desktop_pos 0 )
  1117. unset( _desktop_l10n )
  1118. while( _desktop_pos LESS ${_desktop_len} )
  1119. # pick line
  1120. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\1" _desktop_line "${_desktop_data}" )
  1121. string( REGEX REPLACE "^([^\n]*)\n(.*)" "\\2" _desktop_data "${_desktop_data}" )
  1122. math( EXPR _desktop_pos "${_desktop_pos}+1" )
  1123. # process line
  1124. if( "${_desktop_line}" MATCHES "^${_keywords_match}[ ]*=" )
  1125. string( REGEX REPLACE "\\\"" "\\\\\"" _desktop_line "${_desktop_line}" )
  1126. string( REGEX REPLACE "^${_keywords_match}[ ]*=[ ]*([^\n]*)" "/*\\1*/i18n(\"\\2\");" _desktop_line "${_desktop_line}" )
  1127. else( )
  1128. set( _desktop_line "" )
  1129. endif( )
  1130. set( _desktop_l10n "${_desktop_l10n}${_desktop_line}\n" )
  1131. endwhile( )
  1132. # write file
  1133. file( WRITE ${_target} "${_desktop_l10n}" )
  1134. endfunction( )