blob: ba98ae7aac574d2d2f52237d45abf90562cb845a [file] [log] [blame]
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00001" Vim script for checking .po files.
2"
Bram Moolenaar595f51c2008-06-09 12:46:00 +00003" Go through the file and verify that:
4" - All %...s items in "msgid" are identical to the ones in "msgstr".
5" - An error or warning code in "msgid" matches the one in "msgstr".
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +00006
7if 1 " Only execute this if the eval feature is available.
8
9" Function to get a split line at the cursor.
10" Used for both msgid and msgstr lines.
11" Removes all text except % items and returns the result.
12func! GetMline()
13 let idline = substitute(getline('.'), '"\(.*\)"$', '\1', '')
14 while line('.') < line('$')
15 +
16 let line = getline('.')
17 if line[0] != '"'
18 break
19 endif
20 let idline .= substitute(line, '"\(.*\)"$', '\1', '')
21 endwhile
22
Bram Moolenaara5792f52005-11-23 21:25:05 +000023 " remove '%', not used for formatting.
24 let idline = substitute(idline, "'%'", '', 'g')
25
Bram Moolenaar1c6136a2009-09-11 11:00:05 +000026 " remove '%' used for plural forms.
27 let idline = substitute(idline, '\\nPlural-Forms: .\+;\\n', '', '')
28
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +000029 " remove everything but % items.
30 return substitute(idline, '[^%]*\(%[-+ #''.0-9*]*l\=[dsuxXpoc%]\)\=', '\1', 'g')
31endfunc
32
Bram Moolenaarec420592016-08-26 15:51:53 +020033" This only works when 'wrapscan' is not set.
Bram Moolenaara411e5d2010-08-04 15:47:08 +020034let s:save_wrapscan = &wrapscan
Bram Moolenaarec420592016-08-26 15:51:53 +020035set nowrapscan
Bram Moolenaara411e5d2010-08-04 15:47:08 +020036
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +000037" Start at the first "msgid" line.
Bram Moolenaar7f937032017-07-19 14:34:42 +020038let wsv = winsaveview()
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +0000391
Bram Moolenaarec420592016-08-26 15:51:53 +020040/^msgid\>
41
42" When an error is detected this is set to the line number.
43" Note: this is used in the Makefile.
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +000044let error = 0
45
46while 1
47 if getline(line('.') - 1) !~ "no-c-format"
Bram Moolenaarec420592016-08-26 15:51:53 +020048 " go over the "msgid" and "msgid_plural" lines
49 let prevfromline = 'foobar'
50 while 1
51 let fromline = GetMline()
52 if prevfromline != 'foobar' && prevfromline != fromline
53 echomsg 'Mismatching % in line ' . (line('.') - 1)
54 echomsg 'msgid: ' . prevfromline
55 echomsg 'msgid ' . fromline
56 if error == 0
57 let error = line('.')
58 endif
59 endif
60 if getline('.') !~ 'msgid_plural'
61 break
62 endif
63 let prevfromline = fromline
64 endwhile
65
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +000066 if getline('.') !~ '^msgstr'
Bram Moolenaarec420592016-08-26 15:51:53 +020067 echomsg 'Missing "msgstr" in line ' . line('.')
68 if error == 0
69 let error = line('.')
70 endif
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +000071 endif
Bram Moolenaarec420592016-08-26 15:51:53 +020072
73 " check all the 'msgstr' lines
74 while getline('.') =~ '^msgstr'
75 let toline = GetMline()
76 if fromline != toline
77 echomsg 'Mismatching % in line ' . (line('.') - 1)
78 echomsg 'msgid: ' . fromline
79 echomsg 'msgstr: ' . toline
80 if error == 0
81 let error = line('.')
82 endif
83 endif
84 if line('.') == line('$')
85 break
86 endif
87 endwhile
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +000088 endif
89
Bram Moolenaarec420592016-08-26 15:51:53 +020090 " Find next msgid. Quit when there is no more.
91 let lnum = line('.')
92 silent! /^msgid\>
93 if line('.') == lnum
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +000094 break
95 endif
96endwhile
97
Bram Moolenaar595f51c2008-06-09 12:46:00 +000098" Check that error code in msgid matches the one in msgstr.
99"
100" Examples of mismatches found with msgid "E123: ..."
101" - msgstr "E321: ..." error code mismatch
102" - msgstr "W123: ..." warning instead of error
103" - msgstr "E123 ..." missing colon
104" - msgstr "..." missing error code
105"
1061
107if search('msgid "\("\n"\)\?\([EW][0-9]\+:\).*\nmsgstr "\("\n"\)\?[^"]\@=\2\@!') > 0
Bram Moolenaarec420592016-08-26 15:51:53 +0200108 echomsg 'Mismatching error/warning code in line ' . line('.')
109 if error == 0
110 let error = line('.')
111 endif
Bram Moolenaar595f51c2008-06-09 12:46:00 +0000112endif
113
Bram Moolenaar7f937032017-07-19 14:34:42 +0200114func! CountNl(first, last)
115 let nl = 0
116 for lnum in range(a:first, a:last)
117 if getline(lnum) =~ '\\n'
118 let nl += 1
119 endif
120 endfor
121 return nl
122endfunc
123
124" Check that the \n at the end of the msid line is also present in the msgstr
125" line. Skip over the header.
126/^"MIME-Version:
127while 1
128 let lnum = search('^msgid\>')
129 if lnum <= 0
130 break
131 endif
132 let strlnum = search('^msgstr\>')
133 let end = search('^$')
134 if end <= 0
135 let end = line('$') + 1
136 endif
137 let origcount = CountNl(lnum, strlnum - 1)
138 let transcount = CountNl(strlnum, end - 1)
139 " Allow for a few more or less line breaks when there are 2 or more
140 if origcount != transcount && (origcount <= 2 || transcount <= 2)
141 echomsg 'Mismatching "\\n" in line ' . line('.')
142 if error == 0
143 let error = lnum
144 endif
145 endif
146endwhile
147
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +0000148if error == 0
Bram Moolenaar7f937032017-07-19 14:34:42 +0200149 " If all was OK restore the view.
150 call winrestview(wsv)
Bram Moolenaarec420592016-08-26 15:51:53 +0200151 echomsg "OK"
152else
153 exe error
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +0000154endif
155
Bram Moolenaara411e5d2010-08-04 15:47:08 +0200156let &wrapscan = s:save_wrapscan
157unlet s:save_wrapscan
158
Bram Moolenaar1d94f9b2005-08-04 21:29:45 +0000159endif