Antes de tudo, você precisa informar ao PHP qual localidade e domínio você está usando.
putenv("LANG=da_DK");
setlocale('LC_ALL', "da_DK");
bindtextdomain("mycatalog", "./locale/");
textdomain("mycatalog");
Neste caso estou tendo uma tradução dinamarquesa e um arquivo chamado mycatalog.mo (e .po). Esses arquivos são colocados (da sua raiz) aqui:locale/da_DK/LC_MESSAGES/mycatalog.mo/po
Para mostrar sua tradução, você fará o seguinte:
echo _("Hello world"); // Which would become "Hej verden"
_(); é um alias de gettext(); A coisa inteligente sobre gettexts é que, se não houver tradução, você não terá um código de idioma feio como "MSG_HELLO_WORLD" em sua interface do usuário, mas uma alternativa melhor:simplesmente o texto em inglês simples.
No arquivo messages.po você deve ter todas as mensagens (diferencia maiúsculas de minúsculas e também com relação a vírgulas, pontos, dois pontos etc.) neste formulário:
msgid "Hello world!"
msgstr "Hej verden!"
Quando você adicionar isso ao seu arquivo .po, abra este arquivo no poedit, clique em "Salvar" e ele gerará um arquivo .mo. Este arquivo é carregado para o mesmo diretório que o arquivo .po (normalmente algo como \locale\da_DK\LC_MESSAGES\ da raiz do script)
Para traduzir conteúdo dinâmico/variável você pode usar - entre outras coisas - sprintf, desta forma:
echo sprintf(_("My name is %s"), $name);
Neste caso o %s irá ocorrer no arquivo .po; Quando você tiver a string traduzida (que contém o %s), o sprintf irá certificar-se de substituir o %s pelo conteúdo da variável. SE a variável também deve ser traduzida, você pode fazer isso:
echo sprintf(_("The color of my house is %s"), _($color));
Então você não precisa de uma frase completa para cada cor, mas ainda consegue traduzir as cores.
É importante notar que na primeira vez que um .mo é executado no servidor, ele é armazenado em cache - e não há como remover esse arquivo do cache sem reiniciar (o Apache ou algo semelhante em si deve ser suficiente). Isso significa que quaisquer alterações feitas no .mo após a primeira vez que ele for usado não serão efetivadas. Existem vários hacks para contornar isso, mas honestamente, eles geralmente não são muito bonitos (eles incluem copiar o .mo, adicionar o time() atrás dele e depois importá-lo e armazená-lo novamente). Este último parágrafo só tem importância se você não for traduzir tudo de uma vez, mas em partes.
Se você quiser criar sua própria ferramenta de tradução em algum momento, esta ferramenta ajuda você a converter .po para .mo usando PHP:
http://www.josscrowcroft.com/2011/code/php-mo-convert-gettext-po-file-to-binary-mo-file-php/