summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/po.pm
blob: dbeb0b481ac2cd0d4114d397bfedc39a002becfa (plain)
  1. #!/usr/bin/perl
  2. # .po as a wiki page type
  3. # inspired by the GPL'd po4a-translate,
  4. # which is Copyright 2002, 2003, 2004 by Martin Quinson (mquinson#debian.org)
  5. package IkiWiki::Plugin::po;
  6. use warnings;
  7. use strict;
  8. use IkiWiki 2.00;
  9. use Encode;
  10. use Locale::Po4a::Chooser;
  11. use File::Temp;
  12. sub import {
  13. hook(type => "getsetup", id => "po", call => \&getsetup);
  14. hook(type => "targetpage", id => "po", call => \&targetpage);
  15. hook(type => "filter", id => "po", call => \&filter);
  16. hook(type => "htmlize", id => "po", call => \&htmlize);
  17. }
  18. sub getsetup () { #{{{
  19. return
  20. plugin => {
  21. safe => 0,
  22. rebuild => 1, # format plugin
  23. },
  24. po_supported_languages => {
  25. type => "string",
  26. example => { 'fr' => { 'name' => 'Français' },
  27. 'es' => { 'name' => 'Castellano' },
  28. 'de' => { 'name' => 'Deutsch' },
  29. },
  30. safe => 1,
  31. rebuild => 1,
  32. },
  33. } #}}}
  34. sub targetpage (@) { #{{{
  35. my %params = @_;
  36. my $page=$params{page};
  37. my $ext=$params{ext};
  38. if (! IkiWiki::PageSpec::match_istranslation($page, $page)) {
  39. return;
  40. }
  41. my ($masterpage, $lang) = ($page =~ /(.*)[.]([a-z]{2})$/);
  42. if (! $config{usedirs} || $page eq 'index') {
  43. return $masterpage.".".$ext.".".$lang;
  44. }
  45. else {
  46. return $masterpage."/index.".$ext.".".$lang;
  47. }
  48. } #}}}
  49. # We use filter to convert PO to the master page's type,
  50. # since other plugins should not work on PO files
  51. sub filter (@) { #{{{
  52. my %params = @_;
  53. my $page = $params{page};
  54. my $content = decode_utf8(encode_utf8($params{content}));
  55. # decide if this is a PO file that should be converted into a translated document,
  56. # and perform various sanity checks
  57. if (! IkiWiki::PageSpec::match_istranslation($page, $page)) {
  58. return $content;
  59. }
  60. my ($masterpage, $lang) = ($page =~ /(.*)[.]([a-z]{2})$/);
  61. my $file=srcfile(exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page});
  62. my $masterfile = srcfile($pagesources{$masterpage});
  63. my (@pos,@masters);
  64. push @pos,$file;
  65. push @masters,$masterfile;
  66. my %options = (
  67. "markdown" => (pagetype($masterfile) eq 'mdwn') ? 1 : 0,
  68. );
  69. my $doc=Locale::Po4a::Chooser::new('text',%options);
  70. $doc->process(
  71. 'po_in_name' => \@pos,
  72. 'file_in_name' => \@masters,
  73. 'file_in_charset' => 'utf-8',
  74. 'file_out_charset' => 'utf-8',
  75. ) or error("[po/filter:$file]: failed to translate");
  76. my ($percent,$hit,$queries) = $doc->stats();
  77. my $tmpfh = File::Temp->new(TEMPLATE => "/tmp/ikiwiki-po-filter-out.XXXXXXXXXX");
  78. my $tmpout = $tmpfh->filename;
  79. $doc->write($tmpout) or error("[po/filter:$file] could not write $tmpout");
  80. $content = readfile($tmpout) or error("[po/filter:$file] could not read $tmpout");
  81. return $content;
  82. } #}}}
  83. sub htmlize (@) { #{{{
  84. my %params=@_;
  85. my $page = $params{page};
  86. my $content = $params{content};
  87. my ($masterpage, $lang) = ($page =~ /(.*)[.]([a-z]{2})$/);
  88. my $masterfile = srcfile($pagesources{$masterpage});
  89. # force content to be htmlize'd as if it was the same type as the master page
  90. return IkiWiki::htmlize($page, $page, pagetype($masterfile), $content);
  91. } #}}}
  92. package IkiWiki::PageSpec;
  93. sub match_istranslation ($;@) { #{{{
  94. my $page=shift;
  95. my $wanted=shift;
  96. my %params=@_;
  97. my $file=exists $params{file} ? $params{file} : $IkiWiki::pagesources{$page};
  98. if (! defined $file) {
  99. return IkiWiki::FailReason->new("no file specified");
  100. }
  101. if (! IkiWiki::pagetype($page) eq 'po') {
  102. return IkiWiki::FailReason->new("is not a PO file");
  103. }
  104. my ($masterpage, $lang) = ($page =~ /(.*)[.]([a-z]{2})$/);
  105. if (! defined $masterpage || ! defined $lang
  106. || ! (length($masterpage) > 0) || ! (length($lang) > 0)) {
  107. return IkiWiki::FailReason->new("is not named like a translation file");
  108. }
  109. if (! defined $IkiWiki::pagesources{$masterpage}) {
  110. return IkiWiki::FailReason->new("the master page does not exist");
  111. }
  112. if (! defined $IkiWiki::config{po_supported_languages}{$lang}) {
  113. return IkiWiki::FailReason->new("language $lang is not supported");
  114. }
  115. return IkiWiki::SuccessReason->new("page $page is a translation");
  116. } #}}}
  117. 1