diff --git a/fr-fr/lua-fr.html.markdown b/fr-fr/lua-fr.html.markdown
new file mode 100644
index 00000000..e3979f08
--- /dev/null
+++ b/fr-fr/lua-fr.html.markdown
@@ -0,0 +1,450 @@
+---
+language: lua
+filename: learnlua-fr.lua
+contributors:
+ - ["Tyler Neylon", "http://tylerneylon.com/"]
+translators:
+ - ["Roland Yonaba", "http://github.com/Yonaba"]
+lang: fr-fr
+---
+
+```lua
+-- Les commentaires unilignes commencent par un double-tiret.
+
+--[[
+ Les doubles crochets ouverts ([[) et fermés (]]) à la suite
+ du double-tiret permettent d'avoir des commentaires
+ multilignes.
+--]]
+
+----------------------------------------------------
+-- 1. Variables et contrôle d'exécution.
+----------------------------------------------------
+
+num = 42 -- Tous les nombres sont de type double.
+-- Rassurez vous cependant, les doubles stockés sur 64-bits
+-- en réservent 52 pour la valeur exacte des entiers. La
+-- précision n'est donc pas un problème pour tout entier qui
+-- peut être codé sur moins de 52 bits.
+
+s = 'walternate' -- Chaines de caractères immuables comme en Python.
+t = "une chaine avec des guillemets doubles"
+u = [[les double crochets permettent
+ d'avoir une chaine de caractères
+ sur plusieurs lignes.]]
+t = nil -- Affecte la valeur nulle à t; Lua possède un ramasse-miettes
+
+-- Le do/end définit un bloc de code
+while num < 50 do
+ num = num + 1 -- Pas d'opérateurs de type ++ ou +=.
+end
+
+-- Les structures en if:
+if num > 40 then
+ print('supérieur à 40')
+elseif s ~= 'walternate' then -- ~= : est différent de.
+ -- Le test d'égalité se fait avec == comme en Python.
+ io.write('inférieur à 40\n') -- Ecrit par defaut sur la sortie stdout.
+else
+ -- Les variables sont globales par défaut.
+ thisIsGlobal = 5 -- le style camelCase est courant.
+
+ -- Une variable locale est déclarée avec le mot-clé local:
+ local line = io.read() -- Permet de lire la ligne suivante dans stdin.
+
+ -- .. est l'opérateur de concaténation:
+ print("L'hiver approche, " .. line)
+end
+
+-- Les variables non définies reçoivent par défaut la valeur nil.
+foo = anUnknownVariable -- Maintenant, foo = nil.
+
+aBoolValue = false
+
+-- Seuls nil et false sont des valeurs fausses.
+-- Mais 0 et '' sont des valeurs vraies!
+if not aBoolValue then print('etait faux') end
+
+-- L'évaluation du 'or' et du 'and' est court-circuitée.
+-- Comme avec les ternaires du C et de JS: a?b:c
+ans = aBoolValue and 'oui' or 'non' --> 'non'
+
+karlSum = 0
+for i = 1, 100 do -- Les bornes sont incluses dans l'intervalle.
+ karlSum = karlSum + i
+end
+
+-- Utilisez "100, 1, -1" pour la décrémentation:
+fredSum = 0
+for j = 100, 1, -1 do fredSum = fredSum + j end
+
+-- En général, l'intervalle est début, fin[, pas].
+
+-- Un autre type de boucle:
+repeat
+ print('the way of the future')
+ num = num - 1
+until num == 0
+
+
+----------------------------------------------------
+-- 2. Fonctions.
+----------------------------------------------------
+
+function fib(n)
+ if n < 2 then return n end
+ return fib(n - 2) + fib(n - 1)
+end
+
+-- Lua implémente les fermetures et les fonctions anonymes:
+function adder(x)
+ -- La fonction retournée est créée lorsque adder est appelé
+ -- et elle se rappelle de la valeur de x.
+ return function (y) return x + y end
+end
+a1 = adder(9)
+a2 = adder(36)
+print(a1(16)) --> 25
+print(a2(64)) --> 100
+
+-- Les valeurs de retour, les appels de fonction, les assignations
+-- supportent tous les listes qui peuvent ne pas correspondre en longueur.
+-- Dans ce cas, les variables à assigner en supplément recoivent nil
+-- tandis que les valeurs à attribuer en supplément sont ignorées
+
+x, y = 1, 2 -- x = 1 et y = 2
+x, y, z = 1, 2 -- x = 1, y = 2 et z = nil
+x, y, z = 1, 2, 3, 4 -- x = 1, y = 2, z = 3, et 4 est ignoré.
+
+function bar(a, b, c)
+ print(a, b, c)
+ return 4, 8, 15, 16, 23, 42
+end
+
+x, y = bar('zaphod') --> affiche "zaphod nil nil"
+-- x = 4, y = 8, les valeurs 15 à 42 sont ignorées.
+
+-- Les fonctions sont des valeurs de première classe
+-- et peuvent être locales/globales.
+-- Les déclarations suivantes sont identiques:
+function f(x) return x * x end
+f = function (x) return x * x end
+
+-- Il en va de même pour les déclarations suivantes:
+local function g(x) return math.sin(x) end
+local g = function(x) return math.sin(x) end
+-- Sauf que pour le dernier cas, même si local g = function(x)
+-- est équivalent à local function g(x), il n'est pas possible
+-- de faire appel à g à l'intérieur du corps de la fonction (récursion)
+
+-- A moins de déclarer la fonction auparavant:
+local g; g = function (x) return math.sin(x) end
+
+-- A propos, les fonctions trigonométriques interprètent
+-- leurs arguments en radians.
+print(math.cos(math.pi)) -- affiche "-1"
+print(math.sin(math.pi)) -- affiche "0"
+
+-- Lorsqu'une fonction est appellée avec un seul argument qui est une chaine,
+-- les parenthèses peuvent être omises:
+print 'hello' -- équivalent à print('hello').
+
+-- Lorsqu'une fonction est appellée avec un seul argument qui est une table,
+-- les parenthèses peuvent aussi être omises.
+print {} -- équivalent à print({}).
+
+
+----------------------------------------------------
+-- 3. Tables.
+----------------------------------------------------
+
+-- Tables = Seule structure de données en Lua;
+-- Ce sont des listes assotiatives.
+-- Elles sont similaires aux tables PHP ou aux objets JS :
+-- des tables-dictionnaires que l'on peut utiliser en tant que listes.
+
+-- Tables en tant que dictionnaires:
+
+-- Les clés sont des chaines de caractères par défaut:
+t = {key1 = 'valeur1', key2 = false}
+
+-- Elles peuvent être indexées avec la notation en point, comme en JS:
+print(t.key1) -- Affiche "valeur1".
+t.newKey = {} -- Ajoute une nouvelle paire clé/valeur.
+t.key2 = nil -- Supprime la clé "key2" de la table.
+
+-- Notation littérale pour toute valeur non nulle en tant que clé:
+u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'}
+print(u[6.28]) -- affiche "tau"
+
+-- La correspondance des clés se fait par valeur pour
+-- les nombres et les chaines, mais par référence pour les tables.
+a = u['@!#'] -- a = 'qbert'.
+b = u[{}] -- On pourrait s'attendre à 1729, mais l'on obtient nil:
+-- b = nil car la clé utilisée n'est pas le même objet que celui
+-- utilisé pour stocker la valeur originale 1729.
+
+-- Si une fonction prend en argument une seule table, l'on peut
+-- omettre les parenthèses:
+function h(x) print(x.key1) end
+h{key1 = 'Sonmi~451'} -- Affiche 'Sonmi~451'.
+
+for key, val in pairs(u) do -- Parcours d'une table.
+ print(key, val)
+end
+
+-- _G est une table spéciale contenant toutes les variables globales,
+-- et donc elle même.
+print(_G['_G'] == _G) -- Affiche 'true'.
+
+-- Tables en tant que listes:
+
+-- De manière implicite, les clés sont des nombres entiers:
+v = {'value1', 'value2', 1.21, 'gigawatts'}
+for i = 1, #v do -- #v retourne la taille d'une table si elle est une liste.
+ print(v[i]) -- Attention, en Lua, les index commencent à 1!
+end
+-- Il n'existe pas vraiment de type 'liste' en Lua, v est juste
+-- une table avec des clés qui sont des nombres entiers consécutifs
+-- commençant à 1. Lua le traite comme étant une liste.
+
+----------------------------------------------------
+-- 3.1 Métatables and métaméthodes.
+----------------------------------------------------
+
+-- Une table peut avoir une métatable qui confère à la table
+-- un patron/prototype de conception (surcharge d'opération). Nous verrons
+-- dans la suite comment les métatables imitent le prototypage de JS.
+
+f1 = {a = 1, b = 2} -- Représente la fraction a/b.
+f2 = {a = 2, b = 3}
+
+-- Ceci créée une erreur:
+-- s = f1 + f2
+
+metafraction = {}
+function metafraction.__add(f1, f2)
+ local sum = {}
+ sum.b = f1.b * f2.b
+ sum.a = f1.a * f2.b + f2.a * f1.b
+ return sum
+end
+
+setmetatable(f1, metafraction)
+setmetatable(f2, metafraction)
+
+s = f1 + f2 -- appèle __add(f1, f2) de la métatable de f1
+
+-- f1, f2 ne possède pas de clé qui pointent vers leur métatable, comme
+-- avec les prototypes en JS. Mais l'on peut utiliser getmetatable(f1).
+-- La métatable est une table normale avec des clés prédéfinie, comme __add.
+
+-- Mais la ligne suivante génère une erreur puisque s n'a pas de métatable:
+-- t = s + s
+-- En implémentant de l'orienté-objet, comme nous le verrons dans la suite,
+-- le problème est résolu.
+
+-- Une clé __index dans une métatable mt surcharge l'indexation dans sa table t
+-- si la clé est absente de cette table t:
+defaultFavs = {animal = 'gru', food = 'donuts'}
+myFavs = {food = 'pizza'}
+setmetatable(myFavs, {__index = defaultFavs})
+eatenBy = myFavs.animal -- Affiche "gru"! merci à la métatable!
+
+-- Ainsi donc, un accès direct à une valeur dans une table via une clé
+-- inexistante (ce qui normalement retourne "nil") conduira à exploiter
+-- le champ __index de la métatable. Cela peut être récursif.
+
+-- Le champ __index peut aussi être une fonction (tbl, clé)
+-- ce qui permet une gestion plus souple des indexations.
+
+-- Les clés __index, __add,... sont appelées métaméthodes.
+-- En voici la liste complète:
+
+-- __add(a, b) pour a + b
+-- __sub(a, b) pour a - b
+-- __mul(a, b) pour a * b
+-- __div(a, b) pour a / b
+-- __mod(a, b) pour a % b
+-- __pow(a, b) pour a ^ b
+-- __unm(a) pour -a
+-- __concat(a, b) pour a .. b
+-- __len(a) pour #a
+-- __eq(a, b) pour a == b
+-- __lt(a, b) pour a < b
+-- __le(a, b) pour a <= b
+-- __index(a, b) pour a.b
+-- __newindex(a, b, c) pour a.b = c
+-- __call(a, ...) pour a(...)
+
+----------------------------------------------------
+-- 3.2 Pseudo-orienté objet et héritage.
+----------------------------------------------------
+
+-- Lua n'implémente pas d'orienté objet par défaut.
+-- Mais il reste possible d'imiter de plusieurs manières
+-- le concept de "classe" grâce aux tables et aux métatables.
+
+-- L'explication pour l'exemple qui suit vient juste après.
+
+Dog = {} -- 1.
+
+function Dog:new() -- 2.
+ local newObj = {sound = 'woof'} -- 3.
+ self.__index = self -- 4.
+ return setmetatable(newObj, self) -- 5.
+end
+
+function Dog:makeSound() -- 6.
+ print('Je dis: ' .. self.sound..'!')
+end
+
+mrDog = Dog:new() -- 7.
+mrDog:makeSound() -- 'Je dis: woof! -- 8.
+
+-- 1. Dog agit comme une classe; c'est une simple table.
+-- 2. L'expression tbl:fn(...) est identique à
+-- tbl.fn(self, ...)
+-- La notation : permet de passer par défaut un premier
+-- argument appellé "self" à la fonction tbl.fn
+-- Voir 7 & 8 ci-après pour comprendre comment self prend
+-- sa valeur.
+-- 3. newObj sera une instance de la classe Dog.
+-- 4. self = la classe instanciée. Souvent, self = Dog, mais
+-- cela peut changer du fait de l'héritage.
+-- newObj reçoit les fonctions de self si l'__index des
+-- métatables de newObj et de self pointent vers self.
+-- 5. Rappel: setmetatable retourne son premier argument.
+-- 6. La notation : fonctionne comme au 2, mais cette fois, self
+-- est une instance au lieu d'être une classe.
+-- 7. Similaire à Dog.new(Dog), donc self = Dog dans new().
+-- 8. Similaire à mrDog.makeSound(mrDog); self = mrDog.
+
+----------------------------------------------------
+
+-- Exemple d'héritage:
+
+LoudDog = Dog:new() -- 1.
+
+function LoudDog:makeSound()
+ local s = self.sound .. ' ' -- 2.
+ print(s .. s .. s..'!')
+end
+
+seymour = LoudDog:new() -- 3.
+seymour:makeSound() -- 'woof woof woof!' -- 4.
+
+-- 1. LoudDog reçoit les méthodes et les variables de Dog.
+-- 2. self possède une clé 'sound', reçue de new(), voir 3.
+-- 3. Similaire à LoudDog.new(LoudDog) et traduit en Dog.new(LoudDog),
+-- puisque LoudDog ne possède pas de clé 'new', mais a une métatable
+-- qui a la clé __index = Dog.
+-- Résulat: la métatable de seymour est LoudDog, et
+-- LoudDog.__index = LoudDog. Donc seymour.key deviendra soit égal à
+-- seymour.key, LoudDog.key, Dog.key, selon le fait qu'il s'agira
+-- de la première table ayant la clé 'key' en question, en remontant
+-- dans la hiérarchie.
+-- 4. La clé 'makeSound' est trouvée dans LoudDog; cela est similaire
+-- à LoudDog.makeSound(seymour).
+
+-- Si besoin est, la méthode new() de la sous-classe est
+-- identique à la méthode new() de sa classe mère:
+function LoudDog:new()
+ local newObj = {}
+ -- Prépare self à être la superclasse de newObj:
+ self.__index = self
+ return setmetatable(newObj, self)
+end
+
+----------------------------------------------------
+-- 4. Modules.
+----------------------------------------------------
+
+
+--[[ Cette section est mise en commentaire afin que le reste du
+-- ce script reste exécutable.
+```
+
+```lua
+-- Supposons que le fichier mod.lua contienne ceci:
+local M = {}
+
+local function sayMyName()
+ print('Hrunkner')
+end
+
+function M.sayHello()
+ print('hello')
+ sayMyName()
+end
+
+return M
+
+-- Un autre fichier peut exploiter le contenu défini dans mod.lua's:
+local mod = require('mod') -- Exécute le fichier mod.lua.
+
+-- require est le moyen par défaut d'inclure des modules.
+-- require agit comme: (si non trouvé en cache; voir ci-après)
+local mod = (function ()
+
+end)()
+-- Comme si le contenu de mod.lua est enveloppé dans le corps d'une fonction,
+-- si bien que les variables locales contenues dans mod.lua deviennent
+-- inaccessibles en dehors de ce module.
+
+-- Le code suivant fonctionne car mod = M (dans mod.lua):
+mod.sayHello() -- Dis bonjour à Hrunkner.
+
+-- Le code suivant génère une erreur car sayMyName est local à mod.lua:
+mod.sayMyName() -- erreur!
+
+-- Les valeurs retournées par require sont mises en cache, ce qui fait
+-- qu'un module est toujours chargé une seule fois, même s'il est inclus
+-- avec require à plusieurs reprises.
+
+-- Supposons que mod2.lua contienne le code "print('Hi!')".
+local a = require('mod2') -- Affiche "Hi!"
+local b = require('mod2') -- N'affiche rien; et a = b.
+
+-- dofile est identique à require, sauf qu'il ne fait pas de mise en cache:
+dofile('mod2') --> Hi!
+dofile('mod2') --> Hi! (le code de mod2.lua est encore exécuté)
+
+-- loadfile charge le contenu d'un fichier, sans l'exécuter.
+f = loadfile('mod2') -- L'appel f() exécute le contenu de mod2.lua.
+
+-- loadstring est similaire à loadfile, mais pour les chaines de caractères.
+g = loadstring('print(343)') -- Retourne une fonction.
+g() -- Affiche 343; Rien n'est affiché avant cet appel.
+
+--]]
+
+```
+## Références
+
+*Les références qui suivent sont en Anglais.*
+
+Les sujets non abordés dans ce tutoriel sont couverts en intégralité par
+les librairies standard:
+
+* la librairie string
+* la librairie table
+* la librairie math
+* la librairie io
+* la librairie os
+
+Autres références complémentaires:
+
+* Lua for programmers
+* Courte de référence de Lua
+* Programming In Lua
+* Les manuels de référence Lua
+
+A propos, ce fichier est exécutable. Sauvegardez-le sous le nom learn.lua et
+exécutez-le avec la commande "lua learn.lua" !
+
+Ce tutoriel a été originalement écrit pour tylerneylon.com et est aussi
+disponible en tant que gist.
+Il a été traduit en français par Roland Yonaba (voir son github).
+
+Amusez-vous bien avec Lua!
\ No newline at end of file