Made parser much more robust. Now handles files without whitespace seps.
This commit is contained in:
		
							
								
								
									
										192
									
								
								lib/po.js
									
									
									
									
									
								
							
							
						
						
									
										192
									
								
								lib/po.js
									
									
									
									
									
								
							| @@ -1,30 +1,45 @@ | |||||||
| var fs = require('fs') | var fs = require('fs') | ||||||
|   , util = require('util'); |   , util = require('util'); | ||||||
|  |  | ||||||
|  | function trim(string) { | ||||||
|  |   return string.replace(/^\s+|\s+$/g, ''); | ||||||
|  | }; | ||||||
|  |  | ||||||
| var PO = function() { | var PO = function() { | ||||||
|  |   this.comments = []; | ||||||
|   this.headers = {}; |   this.headers = {}; | ||||||
|   this.items = []; |   this.items = []; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| PO.prototype.save = function(filename, callback) { | PO.prototype.save = function(filename, callback) { | ||||||
|   fs.writeFile(filename, this.toString(), function(err){ |   fs.writeFile(filename, this.toString(), function(err) { | ||||||
|     if (err) throw err; |     if (err) throw err; | ||||||
|     callback && callback(); |     callback && callback(); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| PO.prototype.toString = function() { | PO.prototype.toString = function() { | ||||||
|   var lines = ['msgid ""', 'msgstr ""'] |   var lines = [] | ||||||
|     , that = this; |     , that = this; | ||||||
|  |  | ||||||
|  |   if (this.comments) { | ||||||
|  |     this.comments.forEach(function(comment) { | ||||||
|  |       lines.push('# ' + comment); | ||||||
|  |     }); | ||||||
|  |     lines.push(''); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   lines.push('msgid ""'); | ||||||
|  |   lines.push('msgstr ""'); | ||||||
|  |  | ||||||
|   var keys = Object.keys(this.headers); |   var keys = Object.keys(this.headers); | ||||||
|   keys.forEach(function(key){ |   keys.forEach(function(key) { | ||||||
|     lines.push(util.format('"%s: %s\\n"', key, that.headers[key])); |     lines.push(util.format('"%s: %s\\n"', key, that.headers[key])); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   lines.push(''); |   lines.push(''); | ||||||
|  |  | ||||||
|   this.items.forEach(function(item){ |   this.items.forEach(function(item) { | ||||||
|     lines.push(item.toString()); |     lines.push(item.toString()); | ||||||
|     lines.push(''); |     lines.push(''); | ||||||
|   }); |   }); | ||||||
| @@ -33,36 +48,112 @@ PO.prototype.toString = function() { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| PO.load = function(filename, callback) { | PO.load = function(filename, callback) { | ||||||
|   fs.readFile(filename, 'utf-8', function(err, data){ |   fs.readFile(filename, 'utf-8', function(err, data) { | ||||||
|     if (err) throw err; |     if (err) throw err; | ||||||
|     var po = new PO |     var po = PO.parse(data); | ||||||
|       , parts = data.split(/\n\n/) |  | ||||||
|       , headers = parts.shift().split(/\n/); |  | ||||||
|  |  | ||||||
|     headers.forEach(function(header){ |  | ||||||
|       if (header.match(/^"/)) { |  | ||||||
|         header = header.trim().replace(/^"/, '').replace(/\\n"$/, '');         |  | ||||||
|         var p = header.split(/:/) |  | ||||||
|           , name = p.shift().trim() |  | ||||||
|           , value = p.join(':').trim().replace(/n$/); |  | ||||||
|         po.headers[name] = value; |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     parts.forEach(function(part){ |  | ||||||
|       if (part.length < 1) return; |  | ||||||
|       var item = PO.Item.parse(part); |  | ||||||
|       po.items.push(item); |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     callback && callback(po); |     callback && callback(po); | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | PO.parse = function(data) { | ||||||
|  |     var po = new PO | ||||||
|  |     , sections = data.split(/\n\n/) | ||||||
|  |     , headers = sections.shift() | ||||||
|  |     , lines = sections.join("\n").split(/\n/); | ||||||
|  |  | ||||||
|  |   po.headers = { | ||||||
|  |     'Project-Id-Version': '', | ||||||
|  |     'Report-Msgid-Bugs-To': '', | ||||||
|  |     'POT-Creation-Date': '', | ||||||
|  |     'PO-Revision-Date': '', | ||||||
|  |     'Last-Translator': '', | ||||||
|  |     'Language-Team': '', | ||||||
|  |     'Content-Type': '', | ||||||
|  |     'Content-Transfer-Encoding': '', | ||||||
|  |     'Plural-Forms': '', | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   headers.split(/\n/).forEach(function(header) { | ||||||
|  |     if (header.match(/^#/)) { | ||||||
|  |       po.comments.push(header.replace(/^#\s*/, '')); | ||||||
|  |     } | ||||||
|  |     if (header.match(/^"/)) { | ||||||
|  |       header = header.trim().replace(/^"/, '').replace(/\\n"$/, ''); | ||||||
|  |       var p = header.split(/:/) | ||||||
|  |         , name = p.shift().trim() | ||||||
|  |         , value = p.join(':').trim().replace(/n$/); | ||||||
|  |       po.headers[name] = value; | ||||||
|  |     } | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   var item = new PO.Item() | ||||||
|  |     , context = null | ||||||
|  |     , plural = 0; | ||||||
|  |  | ||||||
|  |   function finish() { | ||||||
|  |     if (item.msgid.length > 0) { | ||||||
|  |       po.items.push(item); | ||||||
|  |       item = new PO.Item(); | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   function extract(string) { | ||||||
|  |     string = trim(string); | ||||||
|  |     string = string.replace(/^[^"]*"|"$/g, ''); | ||||||
|  |     string = string.replace(/\\"/g, '"'); | ||||||
|  |     string = string.replace(/\\\\/g, '\\'); | ||||||
|  |     return string; | ||||||
|  |   }; | ||||||
|  |  | ||||||
|  |   while (lines.length > 0) { | ||||||
|  |     var line = trim(lines.shift()) | ||||||
|  |       , add = false; | ||||||
|  |     if (line.match(/^#:/)) { // Reference | ||||||
|  |       finish(); | ||||||
|  |       item.references.push(trim(line.replace(/^#:/, ''))); | ||||||
|  |     } | ||||||
|  |     else if (line.match(/^#/)) { // Comment | ||||||
|  |       finish(); | ||||||
|  |       item.comments.push(trim(line.replace(/^#/, ''))); | ||||||
|  |     } | ||||||
|  |     else if (line.match(/^msgid_plural/)) { // Plural form | ||||||
|  |       item.msgid_plural = extract(line); | ||||||
|  |       context = 'msgid_plural'; | ||||||
|  |     } | ||||||
|  |     else if (line.match(/^msgid/)) { // Original | ||||||
|  |       finish(); | ||||||
|  |       item.msgid = extract(line); | ||||||
|  |       context = 'msgid'; | ||||||
|  |     } | ||||||
|  |     else if (line.match(/^msgstr/)) { // Translation | ||||||
|  |       var m = line.match(/^msgstr\[(\d+)\]/); | ||||||
|  |       plural = m && m[1] ? parseInt(m[1]) : 0; | ||||||
|  |       item.msgstr[plural] = extract(line); | ||||||
|  |       context = 'msgstr' | ||||||
|  |     } | ||||||
|  |     else { // Probably multiline string or blank | ||||||
|  |       if (line.length > 0) { | ||||||
|  |         if (context == 'msgstr') { | ||||||
|  |           item.msgstr[plural] += extract(line); | ||||||
|  |         } | ||||||
|  |         else if (context == 'msgid') { | ||||||
|  |           item.msgid += extract(line); | ||||||
|  |         } | ||||||
|  |         else if (context == 'msgid_plural') { | ||||||
|  |           item.msgid_plural += extract(line); | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |   finish(); | ||||||
|  |  | ||||||
|  |   return po; | ||||||
|  | }; | ||||||
|  |  | ||||||
| PO.Item = function() { | PO.Item = function() { | ||||||
|   this.msgid = null; |   this.msgid = ''; | ||||||
|   this.references = []; |   this.references = []; | ||||||
|   this.msgid_plural = null; |   this.msgid_plural = ''; | ||||||
|   this.msgstr = []; |   this.msgstr = []; | ||||||
|   this.comments = []; |   this.comments = []; | ||||||
| }; | }; | ||||||
| @@ -71,13 +162,13 @@ PO.Item.prototype.toString = function() { | |||||||
|   var lines = [] |   var lines = [] | ||||||
|     , that = this; |     , that = this; | ||||||
|  |  | ||||||
|   var _processEach = function(keyword, text, i) { |   var _process = function(keyword, text, i) { | ||||||
|     var lines = [] |     var lines = [] | ||||||
|       , parts = text.split(/\n/) |       , parts = text.split(/\n/) | ||||||
|       , index = typeof i != 'undefined' ? util.format('[%d]', i) : ''; |       , index = typeof i != 'undefined' ? util.format('[%d]', i) : ''; | ||||||
|     if (parts.length > 1) { |     if (parts.length > 1) { | ||||||
|       lines.push(util.format('%s%s ""', keyword, index)); |       lines.push(util.format('%s%s ""', keyword, index)); | ||||||
|       parts.forEach(function(part){ |       parts.forEach(function(part) { | ||||||
|         lines.push(util.format('"%s"', part)) |         lines.push(util.format('"%s"', part)) | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| @@ -88,20 +179,20 @@ PO.Item.prototype.toString = function() { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (this.references.length > 0) { |   if (this.references.length > 0) { | ||||||
|     this.references.forEach(function(ref){ |     this.references.forEach(function(ref) { | ||||||
|       lines.push(util.format('#: %s', ref)); |       lines.push(util.format('#: %s', ref)); | ||||||
|     }); |     }); | ||||||
|     ['msgid', 'msgid_plural', 'msgstr'].forEach(function(keyword){ |     ['msgid', 'msgid_plural', 'msgstr'].forEach(function(keyword) { | ||||||
|       var text = that[keyword]; |       var text = that[keyword]; | ||||||
|       if (text != null) { |       if (text != null) { | ||||||
|         if (util.isArray(text) && text.length > 1) { |         if (util.isArray(text) && text.length > 1) { | ||||||
|           text.forEach(function(t, i){ |           text.forEach(function(t, i) { | ||||||
|             lines = lines.concat(_processEach(keyword, t, i)); |             lines = lines.concat(_process(keyword, t, i)); | ||||||
|           }); |           }); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|           text = util.isArray(text) ? text.join() : text; |           text = util.isArray(text) ? text.join() : text; | ||||||
|           lines = lines.concat(_processEach(keyword, text)); |           lines = lines.concat(_process(keyword, text)); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
| @@ -110,37 +201,4 @@ PO.Item.prototype.toString = function() { | |||||||
|   return lines.join("\n"); |   return lines.join("\n"); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| PO.Item.parse = function(chunk) { |  | ||||||
|  |  | ||||||
|   var item = new PO.Item(); |  | ||||||
|   var parts = chunk.split(/msg/); |  | ||||||
|  |  | ||||||
|   var _extract = function(string) { |  | ||||||
|     var lines = string.split(/\n/); |  | ||||||
|     var value = ''; |  | ||||||
|     lines.forEach(function(line){ |  | ||||||
|       var p = line.split(/"/); p.shift(); p.pop(); |  | ||||||
|       value += "\n" + p.join('"'); |  | ||||||
|     }); |  | ||||||
|     return value.trim(); |  | ||||||
|   }; |  | ||||||
|  |  | ||||||
|   parts.forEach(function(part){ |  | ||||||
|     if (part.match(/^#:/)) { |  | ||||||
|       item.references.push(part.replace(/^#:\s/, '')); |  | ||||||
|     } |  | ||||||
|     else if (part.match(/^id\s/)) { |  | ||||||
|       item.msgid = _extract(part); |  | ||||||
|     } |  | ||||||
|     else if (part.match(/id_plural/)) { |  | ||||||
|       item.msgid_plural = _extract(part); |  | ||||||
|     } |  | ||||||
|     else if (part.match(/str/)) { |  | ||||||
|       item.msgstr.push(_extract(part)); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
|  |  | ||||||
|   return item; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| module.exports = PO; | module.exports = PO; | ||||||
							
								
								
									
										175
									
								
								tests/copy.po
									
									
									
									
									
								
							
							
						
						
									
										175
									
								
								tests/copy.po
									
									
									
									
									
								
							| @@ -1,49 +1,150 @@ | |||||||
|  | # French translation of Link (6.x-2.9) | ||||||
|  | # Copyright (c) 2011 by the French translation team | ||||||
|  | #  | ||||||
|  |  | ||||||
| msgid "" | msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PROJECT VERSION\n" | "Project-Id-Version: Link (6.x-2.9)\n" | ||||||
| "POT-Creation-Date: 2011-08-12 09:55-0700\n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "PO-Revision-Date: 2011-12-21 22:30-0800\n" | "POT-Creation-Date: 2011-12-31 23:39+0000\n" | ||||||
| "Last-Translator: Mike Holly <mikejholly@gmail.com>\n" | "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" | ||||||
| "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n" | "Last-Translator: \n" | ||||||
| "MIME-Version: 1.0\n" | "Language-Team: French\n" | ||||||
| "Content-Type: text/plain; charset=utf-8\n" | "Content-Type: text/plain; charset=utf-8\n" | ||||||
| "Content-Transfer-Encoding: 8bit\n" | "Content-Transfer-Encoding: 8bit\n" | ||||||
| "Plural-Forms: nplurals=2; plural=n>1;\n" | "Plural-Forms: nplurals=2; plural=(n!=1);\n" | ||||||
|  | "MIME-Version: 1.0\n" | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:11 |  | ||||||
| msgid "CSV file" |  | ||||||
| msgstr "Archivo CVS" |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:12 |  | ||||||
| msgid "Please make sure the file is formatted correctly (Name, E-mail)" |  | ||||||
| msgstr "Por favor asegúrese de que el archivo tenga el fomato correcto (Nombre, E-mail)" |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:18 |  | ||||||
| msgid "From address" |  | ||||||
| msgstr "Dirección" |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:25 |  | ||||||
| msgid "Plain text" |  | ||||||
| msgstr "Texto plano" |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:26 |  | ||||||
| msgid "HTML markup" |  | ||||||
| msgstr "Formato HTML" |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:28 |  | ||||||
| msgid "Content type" |  | ||||||
| msgstr "Tipo de contenido" |  | ||||||
|  |  | ||||||
| #: strutta_contests_client/strutta_contests_client.module:1381 |  | ||||||
| msgid "" |  | ||||||
| "There is a limit of <strong>1 vote</strong> per entry over <strong>!period</strong>. \n" |  | ||||||
| "      <br>Please come back and vote again in <strong>!retry</strong>." |  | ||||||
| msgstr "" |  | ||||||
| "Hay un límite de <strong>1 voto</strong> por entrada <strong>!period</strong>. \n" |  | ||||||
| "      <br>Por favor vuelve más tarde para votar<strong>!retry</strong>.\"" |  | ||||||
|  |  | ||||||
| #: strutta_submit/strutta_submit.module:113 |  | ||||||
| msgid "@count entry" |  | ||||||
| msgid_plural "@count entries" |  | ||||||
| msgstr[0] "@count entrada" |  | ||||||
| msgstr[1] "@count entradas" |  | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								tests/run.js
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								tests/run.js
									
									
									
									
									
								
							| @@ -1,12 +1,11 @@ | |||||||
| var po = require('../lib/po.js') | var PO = require('../lib/po.js') | ||||||
|   , fs = require('fs') |   , fs = require('fs') | ||||||
|   , assert = require('assert') |   , assert = require('assert') | ||||||
|  |  | ||||||
| po.load('text.po', function(_po){ | PO.load('text.po', function(po) { | ||||||
|   _po.save('copy.po', function(){ |   assert.equal(po.headers['Plural-Forms'], 'nplurals=2; plural=(n!=1);', 'Parsed "Plural-Forms" header.'); | ||||||
|     var orig = fs.readFileSync('text.po'); |   assert.equal(po.items.length, 67, 'Successfully parsed 67 items.'); | ||||||
|     var data = fs.readFileSync('copy.po'); |   var item = po.items.pop(); | ||||||
|     assert.equal(orig, data, 'Saved data is identical to original.'); |   assert.equal(item.comments.length, 1, 'Parsed item comment.'); | ||||||
|   }); |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										265
									
								
								tests/text.po
									
									
									
									
									
								
							
							
						
						
									
										265
									
								
								tests/text.po
									
									
									
									
									
								
							| @@ -1,49 +1,232 @@ | |||||||
|  | # French translation of Link (6.x-2.9) | ||||||
|  | # Copyright (c) 2011 by the French translation team | ||||||
|  | # | ||||||
| msgid "" | msgid "" | ||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PROJECT VERSION\n" | "Project-Id-Version: Link (6.x-2.9)\n" | ||||||
| "POT-Creation-Date: 2011-08-12 09:55-0700\n" | "POT-Creation-Date: 2011-12-31 23:39+0000\n" | ||||||
| "PO-Revision-Date: 2011-12-21 22:30-0800\n" | "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n" | ||||||
| "Last-Translator: Mike Holly <mikejholly@gmail.com>\n" | "Language-Team: French\n" | ||||||
| "Language-Team: LANGUAGE <EMAIL@ADDRESS>\n" |  | ||||||
| "MIME-Version: 1.0\n" | "MIME-Version: 1.0\n" | ||||||
| "Content-Type: text/plain; charset=utf-8\n" | "Content-Type: text/plain; charset=utf-8\n" | ||||||
| "Content-Transfer-Encoding: 8bit\n" | "Content-Transfer-Encoding: 8bit\n" | ||||||
| "Plural-Forms: nplurals=2; plural=n>1;\n" | "Plural-Forms: nplurals=2; plural=(n!=1);\n" | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:11 | msgid "Title" | ||||||
| msgid "CSV file" | msgstr "Titre" | ||||||
| msgstr "Archivo CVS" | msgid "CCK" | ||||||
|  | msgstr "CCK" | ||||||
| #: strutta/strutta.admin.inc:12 | msgid "Content" | ||||||
| msgid "Please make sure the file is formatted correctly (Name, E-mail)" | msgstr "Contenu" | ||||||
| msgstr "Por favor asegúrese de que el archivo tenga el fomato correcto (Nombre, E-mail)" | msgid "Link" | ||||||
|  | msgstr "Lien" | ||||||
| #: strutta/strutta.admin.inc:18 | msgid "Link Target" | ||||||
| msgid "From address" | msgstr "Cible du Lien" | ||||||
| msgstr "Dirección" | msgid "URL" | ||||||
|  | msgstr "URL" | ||||||
| #: strutta/strutta.admin.inc:25 | msgid "Placeholder tokens" | ||||||
| msgid "Plain text" | msgstr "Jetons (tokens) de substitution" | ||||||
| msgstr "Texto plano" |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:26 |  | ||||||
| msgid "HTML markup" |  | ||||||
| msgstr "Formato HTML" |  | ||||||
|  |  | ||||||
| #: strutta/strutta.admin.inc:28 |  | ||||||
| msgid "Content type" |  | ||||||
| msgstr "Tipo de contenido" |  | ||||||
|  |  | ||||||
| #: strutta_contests_client/strutta_contests_client.module:1381 |  | ||||||
| msgid "" | msgid "" | ||||||
| "There is a limit of <strong>1 vote</strong> per entry over <strong>!period</strong>. \n" | "The following placeholder tokens can be used in both paths and titles. " | ||||||
| "      <br>Please come back and vote again in <strong>!retry</strong>." | "When used in a path or title, they will be replaced with the " | ||||||
|  | "appropriate values." | ||||||
| msgstr "" | msgstr "" | ||||||
| "Hay un límite de <strong>1 voto</strong> por entrada <strong>!period</strong>. \n" | "Les ébauches de jetons suivantes peuvent être utilisées à la fois " | ||||||
| "      <br>Por favor vuelve más tarde para votar<strong>!retry</strong>.\"" | "dans les chemins et dans les titres. Lorsqu'elles sont utilisées dans " | ||||||
|  | "un chemin ou un titre, elles seront remplacées par les valeurs " | ||||||
| #: strutta_submit/strutta_submit.module:113 | "appropriées." | ||||||
| msgid "@count entry" | msgid "Optional Title" | ||||||
| msgid_plural "@count entries" | msgstr "Titre Optionnel" | ||||||
| msgstr[0] "@count entrada" | msgid "Required Title" | ||||||
| msgstr[1] "@count entradas" | msgstr "Titre Obligatoire" | ||||||
|  | msgid "No Title" | ||||||
|  | msgstr "Aucun Titre" | ||||||
|  | msgid "Link Title" | ||||||
|  | msgstr "Titre du Lien" | ||||||
|  | msgid "URL Display Cutoff" | ||||||
|  | msgstr "Coupure de l'Affichage de l'URL" | ||||||
|  | msgid "" | ||||||
|  | "If the user does not include a title for this link, the URL will be " | ||||||
|  | "used as the title. When should the link title be trimmed and finished " | ||||||
|  | "with an elipsis (…)? Leave blank for no limit." | ||||||
|  | msgstr "" | ||||||
|  | "Si l'utilisateur n'inclue pas de titre pour ce lien, l'URL sera " | ||||||
|  | "utilisée en tant que titre. A quel endroit le lien devra-t-il être " | ||||||
|  | "coupé et terminé par une ellipse (…) ? Laissez vide pour " | ||||||
|  | "aucune limite." | ||||||
|  | msgid "Default (no target attribute)" | ||||||
|  | msgstr "Par Défaut (aucun attribut de cible)" | ||||||
|  | msgid "Open link in window root" | ||||||
|  | msgstr "Ouvrir le lien dans la fenêtre courante" | ||||||
|  | msgid "Open link in new window" | ||||||
|  | msgstr "Ouvrir le lien dans une nouvelle fenêtre" | ||||||
|  | msgid "Allow the user to choose" | ||||||
|  | msgstr "Autoriser l'utilisateur à choisir" | ||||||
|  | msgid "Additional CSS Class" | ||||||
|  | msgstr "Classe CSS additionnelle" | ||||||
|  | msgid "Not a valid URL." | ||||||
|  | msgstr "Cette URL n'est pas valide." | ||||||
|  | msgid "Titles are required for all links." | ||||||
|  | msgstr "Les titres sont obligatoires pour tous les liens." | ||||||
|  | msgid "Open URL in a New Window" | ||||||
|  | msgstr "Ouvril l'URL dans une Nouvelle Fenêtre" | ||||||
|  | msgid "Defines simple link field types." | ||||||
|  | msgstr "Définit les types de champs \"lien simple\"." | ||||||
|  | msgid "Link URL" | ||||||
|  | msgstr "Url du Lien" | ||||||
|  | msgid "Wildcard" | ||||||
|  | msgstr "Joker" | ||||||
|  | msgid "=" | ||||||
|  | msgstr "=" | ||||||
|  | msgid "Protocol" | ||||||
|  | msgstr "Protocole" | ||||||
|  | msgid "Optional URL" | ||||||
|  | msgstr "URL optionnelle" | ||||||
|  | msgid "Static Title: " | ||||||
|  | msgstr "Titre Statique : " | ||||||
|  | msgid "" | ||||||
|  | "If the link title is optional or required, a field will be displayed " | ||||||
|  | "to the end user. If the link title is static, the link will always use " | ||||||
|  | "the same title. If <a href=\"http://drupal.org/project/token\">token " | ||||||
|  | "module</a> is installed, the static title value may use any other node " | ||||||
|  | "field as its value. Static and token-based titles may include most " | ||||||
|  | "inline XHTML tags such as <em>strong</em>, <em>em</em>, <em>img</em>, " | ||||||
|  | "<em>span</em>, etc." | ||||||
|  | msgstr "" | ||||||
|  | "Si le titre du lien est facultatif ou obligatoire, un champ sera " | ||||||
|  | "affiché à l'utilisateur final. Si le titre du lien est statique, le " | ||||||
|  | "lien utilisera toujours le même titre. Si le <a " | ||||||
|  | "href=\"http://drupal.org/project/token\">module token</a> est " | ||||||
|  | "installé, le titre statique peut utiliser n'importe quel autre champ " | ||||||
|  | "du nœud pour sa valeur. Les titres statiques et basés sur des jetons " | ||||||
|  | "(tokens) peuvent contenir la plupart des balises XHTML en ligne, " | ||||||
|  | "telles que <em>strong</em>, <em>em</em>, <em>img</em>, <em>span</em>, " | ||||||
|  | "etc." | ||||||
|  | msgid "Allow user-entered tokens" | ||||||
|  | msgstr "Autoriser les jetons (tokens) saisis par l'utilisateur" | ||||||
|  | msgid "" | ||||||
|  | "Checking will allow users to enter tokens in URLs and Titles on the " | ||||||
|  | "node edit form. This does not affect the field settings on this page." | ||||||
|  | msgstr "" | ||||||
|  | "Le fait de cocher cette case permettra aux utilisateurs de saisir des " | ||||||
|  | "jetons dans les URL et les Titres dans le formulaire d'édition du " | ||||||
|  | "nœud. Ceci n'affecte pas les configurations de champ sur cette page." | ||||||
|  | msgid "Rel Attribute" | ||||||
|  | msgstr "Attribut Rel" | ||||||
|  | msgid "" | ||||||
|  | "When output, this link will have this rel attribute. The most common " | ||||||
|  | "usage is <a " | ||||||
|  | "href=\"http://en.wikipedia.org/wiki/Nofollow\">rel="nofollow"</a> " | ||||||
|  | "which prevents some search engines from spidering entered links." | ||||||
|  | msgstr "" | ||||||
|  | "Quand il sera affiché, ce lien aura cet attribut rel. L'usage le plus " | ||||||
|  | "commun est <a " | ||||||
|  | "href=\"http://fr.wikipedia.org/wiki/Nofollow\">rel="nofollow"</a> " | ||||||
|  | "qui empêche certains moteurs de recherche d'aspirer les liens suivis." | ||||||
|  | msgid "A default title must be provided if the title is a static value" | ||||||
|  | msgstr "" | ||||||
|  | "Un titre pas défaut doit être fourni si le titre est une valeur " | ||||||
|  | "statique" | ||||||
|  | msgid "At least one title or URL must be entered." | ||||||
|  | msgstr "Vous devez saisir au moins un titre ou une URL." | ||||||
|  | msgid "You cannot enter a title without a link url." | ||||||
|  | msgstr "Vous ne pouvez pas saisir un titre dans une url de lien." | ||||||
|  | msgid "Title, as link (default)" | ||||||
|  | msgstr "Titre, en tant que lien (par défaut)" | ||||||
|  | msgid "URL, as link" | ||||||
|  | msgstr "URL, en tant que lien" | ||||||
|  | msgid "Short, as link with title \"Link\"" | ||||||
|  | msgstr "Court, comme lien avec le titre \"Lien\"" | ||||||
|  | msgid "Label, as link with label as title" | ||||||
|  | msgstr "Étiquette, comme lien avec l'étiquette comme titre" | ||||||
|  | msgid "Separate title and URL" | ||||||
|  | msgstr "Titre et URL séparés" | ||||||
|  | msgid "Validator" | ||||||
|  | msgstr "Validateur" | ||||||
|  | msgid "Is one of" | ||||||
|  | msgstr "Fait partie de" | ||||||
|  | msgid "@label title" | ||||||
|  | msgstr "Titre de @label" | ||||||
|  | msgid "@label protocol" | ||||||
|  | msgstr "Protocole de @label" | ||||||
|  | msgid "@label target" | ||||||
|  | msgstr "Cible de @label" | ||||||
|  | msgid "" | ||||||
|  | "The title to use when this argument is present; it will override the " | ||||||
|  | "title of the view and titles from previous arguments. You can use " | ||||||
|  | "percent substitution here to replace with argument titles. Use \"%1\" " | ||||||
|  | "for the first argument, \"%2\" for the second, etc." | ||||||
|  | msgstr "" | ||||||
|  | "Le titre à utiliser lorsque cet argument est présent ; il écrasera " | ||||||
|  | "le titre de la vue et les titres provenant des arguments précédents. " | ||||||
|  | "Vous pouvez utiliser ici les substitutions de pourcentage pour " | ||||||
|  | "remplacer avec les titres des arguments. Utilisez \"%1\" pour le " | ||||||
|  | "premier argument, \"%2\" pour le second, etc." | ||||||
|  | msgid "Action to take if argument is not present" | ||||||
|  | msgstr "Action à mener si l'argument est absent" | ||||||
|  | msgid "" | ||||||
|  | "If this value is received as an argument, the argument will be " | ||||||
|  | "ignored; i.e, \"all values\"" | ||||||
|  | msgstr "" | ||||||
|  | "Si cette valeur est reçue comme argument, l'argument sera ignoré ; " | ||||||
|  | "correspond à \"toutes les valeurs\"" | ||||||
|  | msgid "Wildcard title" | ||||||
|  | msgstr "Titre du joker" | ||||||
|  | msgid "The title to use for the wildcard in substitutions elsewhere." | ||||||
|  | msgstr "" | ||||||
|  | "Le titre à utiliser pour le joker dans les substitutions partout " | ||||||
|  | "ailleurs." | ||||||
|  | msgid "<Basic validation>" | ||||||
|  | msgstr "<Validation basique>" | ||||||
|  | msgid "Action to take if argument does not validate" | ||||||
|  | msgstr "Actions à mener si l'argument ne passe pas la validation" | ||||||
|  | msgid "" | ||||||
|  | "The protocols displayed here are those globally available. You may add " | ||||||
|  | "more protocols by modifying the <em>filter_allowed_protocols</em> " | ||||||
|  | "variable in your installation." | ||||||
|  | msgstr "" | ||||||
|  | "Les protocoles affichés ici sont ceux disponibles de manière " | ||||||
|  | "globale. Vous pouvez ajouter plus de protocoles en modifiant la " | ||||||
|  | "variable <em>filter_allowed_protocols</em> de votre installation." | ||||||
|  | msgid "Link title" | ||||||
|  | msgstr "Titre du lien" | ||||||
|  | msgid "exposed" | ||||||
|  | msgstr "exposé" | ||||||
|  | msgid "Formatted html link" | ||||||
|  | msgstr "Lien html formaté" | ||||||
|  | msgid "" | ||||||
|  | "Store a title, href, and attributes in the database to assemble a " | ||||||
|  | "link." | ||||||
|  | msgstr "" | ||||||
|  | "Stocker un titre, href et des attributs dans la base de données pour " | ||||||
|  | "les assembler dans un lien." | ||||||
|  | msgid "URL, as plain text" | ||||||
|  | msgstr "URL, texte simple" | ||||||
|  | msgid "@label URL" | ||||||
|  | msgstr "URL de @label" | ||||||
|  | msgid "Validate URL" | ||||||
|  | msgstr "Valider l'URL" | ||||||
|  | msgid "" | ||||||
|  | "If checked, the URL field will be verified as a valid URL during " | ||||||
|  | "validation." | ||||||
|  | msgstr "" | ||||||
|  | "Si coché, la validité du format de l'URL sera verifiée durant la " | ||||||
|  | "validation." | ||||||
|  | msgid "" | ||||||
|  | "If checked, the URL field is optional and submitting a title alone " | ||||||
|  | "will be acceptable. If the URL is omitted, the title will be displayed " | ||||||
|  | "as plain text." | ||||||
|  | msgstr "" | ||||||
|  | "Si coché, le champ URL est optionnel and soumettre un titre seul sera " | ||||||
|  | "accepté. SI l'URL est omise, le titre sera affiché en texte brut." | ||||||
|  | msgid "" | ||||||
|  | "When output, this link will have this class attribute. Multiple " | ||||||
|  | "classes should be separated by spaces." | ||||||
|  | msgstr "" | ||||||
|  | "Lors de l'affichage, le lien aura cet attribut de classe (class). Les " | ||||||
|  | "classes doivent être séparées par des espaces." | ||||||
|  | msgid "Link 'title' Attribute" | ||||||
|  | msgstr "Attribut 'title' du lien" | ||||||
|  | # Comment | ||||||
|  | msgid "Title, as plain text" | ||||||
|  | msgstr "Attribut title, en tant que texte brut" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user