Formatação
É oficial! #LARAVELLUSOPHONE v1.0 chegou com tudo!
On this page
Introdução
Formatação de Moedas
Formatação Automática
Formatação por Região Específica
Opções de Formatação Avançada
Formatação de Números
Números Decimais
Percentuais
Números Grandes
Configurações por País
Portugal
Brasil
Moçambique
Angola
Formatação de Datas
Formatos Automáticos
Formatos Personalizados
Macros do Laravel
String Macros
Collection Macros
Blade Directives
Directivas Personalizadas
Exemplos Práticos em Views
Formatação Condicional
Baseada na Região
Formatação Multi-moeda
Formatação para APIs
Resposta JSON Localizada
Resource Classes Localizadas
Formatação Personalizada
Criar Formatadores Customizados
Registrar Formatadores Personalizados
Usar Formatadores Personalizados
Formatação para Relatórios
Relatórios Financeiros
Export para Excel Localizado
Testes de Formatação
Testes Unitários
Testes de Integração
Próximos Passos
#Formatação de Moedas e Números
#Introdução
O Laravel Lusophone oferece formatação automática e inteligente de valores monetários, números, datas e outros formatos locais baseados na região detectada do utilizador. Cada país lusófono tem suas próprias convenções de formatação que são aplicadas automaticamente.
#Formatação de Moedas
#Formatação Automática
A formatação de moeda é feita automaticamente baseada na região detectada:
Copied!
use Illuminate\Support\Str; // Formata automaticamente baseado na região do utilizador$valor = 1500.50; echo Str::lusophoneCurrency($valor);// Resultados automáticos por país:// 🇵🇹 Portugal: "1.500,50 €"// 🇧🇷 Brasil: "R$ 1.500,50"// 🇲🇿 Moçambique: "1.500,50 MT"// 🇦🇴 Angola: "1.500,50 Kz"// 🇨🇻 Cabo Verde: "1.500,50 Esc"
#Formatação por Região Específica
Copied!
use ArnaldoTomo\LaravelLusophone\Facades\Lusophone; // Forçar formatação para região específica$valor = 1500.50; echo Lusophone::formatCurrency($valor, 'PT'); // "1.500,50 €"echo Lusophone::formatCurrency($valor, 'BR'); // "R$ 1.500,50"echo Lusophone::formatCurrency($valor, 'MZ'); // "1.500,50 MT"echo Lusophone::formatCurrency($valor, 'AO'); // "1.500,50 Kz"
#Opções de Formatação Avançada
Copied!
// Opções personalizadas$opcoes = [ 'show_symbol' => true, // Mostrar símbolo da moeda 'show_code' => false, // Mostrar código da moeda (USD, EUR, etc.) 'decimals' => 2, // Número de casas decimais 'use_accounting' => false, // Formato contabilístico]; echo Lusophone::formatCurrency($valor, 'MZ', $opcoes);// "1.500,50 MT" $opcoes['show_code'] = true;$opcoes['show_symbol'] = false;echo Lusophone::formatCurrency($valor, 'MZ', $opcoes);// "1.500,50 MZN"
#Formatação de Números
#Números Decimais
Copied!
use Illuminate\Support\Str; $numero = 1234.56; // Formatação automática baseada na regiãoecho Str::lusophoneNumber($numero);// 🇵🇹 Portugal: "1.234,56"// 🇧🇷 Brasil: "1.234,56"// 🇲🇿 Moçambique: "1.234,56" // Formatação específica por regiãoecho Lusophone::formatNumber($numero, 'PT'); // "1 234,56" (espaço como separador)echo Lusophone::formatNumber($numero, 'BR'); // "1.234,56" (ponto como separador)echo Lusophone::formatNumber($numero, 'MZ'); // "1.234,56"
#Percentuais
Copied!
$percentual = 0.1532; // 15.32% echo Lusophone::formatPercentage($percentual);// Região PT: "15,32%"// Região BR: "15,32%"// Região MZ: "15,32%" // Com precisão personalizadaecho Lusophone::formatPercentage($percentual, 1);// "15,3%"
#Números Grandes
Copied!
$numeroGrande = 1234567.89; echo Lusophone::formatNumber($numeroGrande);// 🇵🇹 Portugal: "1 234 567,89"// 🇧🇷 Brasil: "1.234.567,89"// 🇲🇿 Moçambique: "1.234.567,89"
#Configurações por País
#Portugal
Copied!
// Formatação portuguesa$config = [ 'currency_symbol' => '€', 'currency_code' => 'EUR', 'currency_position' => 'after', // 1.500,50 € 'decimal_separator' => ',', 'thousands_separator' => ' ', // Espaço 'decimals' => 2,]; echo Lusophone::formatCurrency(1500.50, 'PT');// "1 500,50 €"
#Brasil
Copied!
// Formatação brasileira$config = [ 'currency_symbol' => 'R$', 'currency_code' => 'BRL', 'currency_position' => 'before', // R$ 1.500,50 'decimal_separator' => ',', 'thousands_separator' => '.', 'decimals' => 2,]; echo Lusophone::formatCurrency(1500.50, 'BR');// "R$ 1.500,50"
#Moçambique
Copied!
// Formatação moçambicana$config = [ 'currency_symbol' => 'MT', 'currency_code' => 'MZN', 'currency_position' => 'after', // 1.500,50 MT 'decimal_separator' => ',', 'thousands_separator' => '.', 'decimals' => 2,]; echo Lusophone::formatCurrency(1500.50, 'MZ');// "1.500,50 MT"
#Angola
Copied!
// Formatação angolana$config = [ 'currency_symbol' => 'Kz', 'currency_code' => 'AOA', 'currency_position' => 'after', // 1.500,50 Kz 'decimal_separator' => ',', 'thousands_separator' => '.', 'decimals' => 2,]; echo Lusophone::formatCurrency(1500.50, 'AO');// "1.500,50 Kz"
#Formatação de Datas
#Formatos Automáticos
Copied!
use Carbon\Carbon; $data = Carbon::parse('2024-12-25 15:30:00'); // Formatação automática por regiãoecho Lusophone::formatDate($data);// 🇵🇹 Portugal: "25-12-2024"// 🇧🇷 Brasil: "25/12/2024"// 🇲🇿 Moçambique: "25/12/2024"// 🇦🇴 Angola: "25/12/2024" echo Lusophone::formatDateTime($data);// 🇵🇹 Portugal: "25-12-2024 15:30"// 🇧🇷 Brasil: "25/12/2024 15:30"// 🇲🇿 Moçambique: "25/12/2024 15:30"
#Formatos Personalizados
Copied!
// Data por extensoecho Lusophone::formatDateLong($data);// 🇵🇹 Portugal: "25 de Dezembro de 2024"// 🇧🇷 Brasil: "25 de dezembro de 2024"// 🇲🇿 Moçambique: "25 de Dezembro de 2024" // Data relativaecho Lusophone::formatDateRelative($data);// "há 2 dias", "amanhã", "na próxima semana"
#Macros do Laravel
O Laravel Lusophone adiciona macros úteis ao Str e Collection:
#String Macros
Copied!
use Illuminate\Support\Str; // Formatação de moedaecho Str::lusophoneCurrency(1500.50); // "1.500,50 MT" (baseado na região) // Formatação de númeroecho Str::lusophoneNumber(1234.56); // "1.234,56" // Formatação de percentualecho Str::lusophonePercentage(0.1532); // "15,32%" // Telefone formatadoecho Str::lusophonePhone('+258823456789'); // "+258 82 345 6789" // Documento fiscal formatadoecho Str::lusophoneTaxId('123456789'); // "123 456 789" (NUIT/NIF)
#Collection Macros
Copied!
// Listar países lusófonos$paises = collect()->lusophoneCountries();// [// 'PT' => 'Portugal',// 'BR' => 'Brasil',// 'MZ' => 'Moçambique',// 'AO' => 'Angola',// // ...// ] // Informações de moedas$moedas = collect()->lusophoneCurrencies();// [// 'PT' => ['symbol' => '€', 'code' => 'EUR', 'name' => 'Euro'],// 'BR' => ['symbol' => 'R, 'code' => 'BRL', 'name' => 'Real'],// 'MZ' => ['symbol' => 'MT', 'code' => 'MZN', 'name' => 'Metical'],// // ...// ]
#Blade Directives
#Directivas Personalizadas
Copied!
{{-- Formatação de moeda --}}@currency(1500.50){{-- Resultado: "1.500,50 MT" (baseado na região detectada) --}} @currency(1500.50, 'PT'){{-- Resultado: "1 500,50 €" --}} {{-- Formatação de número --}}@number(1234.56){{-- Resultado: "1.234,56" --}} {{-- Formatação de data --}}@lusophoneDate($produto->created_at){{-- Resultado: "25/12/2024" --}} {{-- Campo formatado --}}@field('tax_id', '123456789'){{-- Resultado: "NUIT: 123456789" (MZ), "NIF: 123456789" (PT) --}}
#Exemplos Práticos em Views
Copied!
{{-- resources/views/products/show.blade.php --}}<div class="product-card"> <h3>{{ $produto->nome }}</h3> <div class="price"> @currency($produto->preco) </div> <div class="details"> <p><strong>SKU:</strong> {{ $produto->sku }}</p> <p><strong>Stock:</strong> @number($produto->stock) unidades</p> <p><strong>Desconto:</strong> @percentage($produto->desconto)</p> <p><strong>Data:</strong> @lusophoneDate($produto->created_at)</p> </div></div>
Copied!
{{-- resources/views/invoices/show.blade.php --}}<div class="invoice"> <h2>Factura #{{ $factura->numero }}</h2> <div class="client-info"> <p><strong>Cliente:</strong> {{ $factura->cliente->nome }}</p> <p><strong>@field('tax_id'):</strong> {{ $factura->cliente->documento_fiscal }}</p> <p><strong>@field('phone'):</strong> @phone($factura->cliente->telefone)</p> </div> <table class="items"> @foreach($factura->itens as $item) <tr> <td>{{ $item->descricao }}</td> <td>@number($item->quantidade)</td> <td>@currency($item->preco_unitario)</td> <td>@currency($item->total)</td> </tr> @endforeach </table> <div class="total"> <strong>Total: @currency($factura->total)</strong> </div> <div class="date"> Emitida em @lusophoneDate($factura->data_emissao) </div></div>
#Formatação Condicional
#Baseada na Região
Copied!
// Formatação condicional baseada na região detectada$valor = 1500.50;$regiao = Lusophone::detectRegion(); $formatado = match ($regiao) { 'PT' => Lusophone::formatCurrency($valor, 'PT'), // "1 500,50 €" 'BR' => Lusophone::formatCurrency($valor, 'BR'), // "R$ 1.500,50" 'MZ' => Lusophone::formatCurrency($valor, 'MZ'), // "1.500,50 MT" 'AO' => Lusophone::formatCurrency($valor, 'AO'), // "1.500,50 Kz" default => Lusophone::formatCurrency($valor, 'MZ'), // Padrão Moçambique};
#Formatação Multi-moeda
Copied!
// Para e-commerce que aceita múltiplas moedasclass Produto extends Model{ protected $fillable = ['nome', 'preco_mzn', 'preco_usd', 'preco_eur']; public function getPrecoFormatadoAttribute() { $regiao = Lusophone::detectRegion(); return match ($regiao) { 'PT' => $this->preco_eur ? Lusophone::formatCurrency($this->preco_eur, 'PT') : 'Preço não disponível', 'MZ' => Lusophone::formatCurrency($this->preco_mzn, 'MZ'), default => $this->preco_usd ? ' . number_format($this->preco_usd, 2) : 'Preço não disponível', }; }}
#Formatação para APIs
#Resposta JSON Localizada
Copied!
// app/Http/Controllers/Api/ProdutoController.php<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller;use ArnaldoTomo\LaravelLusophone\Facades\Lusophone; class ProdutoController extends Controller{ public function show(Produto $produto) { $regiao = Lusophone::detectRegion(); $info_regiao = Lusophone::getCountryInfo($regiao); return response()->json([ 'produto' => [ 'id' => $produto->id, 'nome' => $produto->nome, 'preco' => [ 'raw' => $produto->preco, 'formatted' => Lusophone::formatCurrency($produto->preco, $regiao), 'currency' => $info_regiao['currency'], ], 'stock' => [ 'raw' => $produto->stock, 'formatted' => Lusophone::formatNumber($produto->stock, $regiao), ], 'created_at' => [ 'raw' => $produto->created_at->toISOString(), 'formatted' => Lusophone::formatDate($produto->created_at, $regiao), 'relative' => Lusophone::formatDateRelative($produto->created_at, $regiao), ], ], 'region_info' => $info_regiao, ]); }}
#Resource Classes Localizadas
Copied!
// app/Http/Resources/ProdutoResource.php<?php namespace App\Http\Resources; use Illuminate\Http\Resources\Json\JsonResource;use ArnaldoTomo\LaravelLusophone\Facades\Lusophone; class ProdutoResource extends JsonResource{ public function toArray($request) { $regiao = Lusophone::detectRegion(); return [ 'id' => $this->id, 'nome' => $this->nome, 'descricao' => $this->descricao, 'preco' => [ 'valor' => $this->preco, 'formatado' => Lusophone::formatCurrency($this->preco, $regiao), 'moeda' => Lusophone::getCurrencyInfo($regiao), ], 'dimensoes' => [ 'peso' => Lusophone::formatNumber($this->peso, $regiao) . ' kg', 'comprimento' => Lusophone::formatNumber($this->comprimento, $regiao) . ' cm', ], 'datas' => [ 'criado' => Lusophone::formatDateTime($this->created_at, $regiao), 'atualizado' => Lusophone::formatDateTime($this->updated_at, $regiao), ], ]; }}
#Formatação Personalizada
#Criar Formatadores Customizados
Copied!
// app/Services/CustomLusophoneFormatter.php<?php namespace App\Services; use ArnaldoTomo\LaravelLusophone\Services\BaseFormatter; class CustomLusophoneFormatter extends BaseFormatter{ /** * Formatação personalizada para relatórios empresariais */ public function formatBusinessCurrency($amount, $region = null) { $region = $region ?: $this->detectRegion(); $formatted = $this->formatCurrency($amount, $region); // Adicionar contexto empresarial return match ($region) { 'PT' => $formatted . ' (IVA incluído)', 'BR' => $formatted . ' (impostos incluídos)', 'MZ' => $formatted . ' (IVA incluído)', 'AO' => $formatted . ' (impostos incluídos)', default => $formatted, }; } /** * Formatação de quantidade com unidades locais */ public function formatQuantityWithUnit($quantity, $unit, $region = null) { $region = $region ?: $this->detectRegion(); $formattedQuantity = $this->formatNumber($quantity, $region); // Adaptar unidades por região $units = [ 'kg' => [ 'PT' => 'kg', 'BR' => 'kg', 'MZ' => 'kg', 'AO' => 'kg', ], 'litre' => [ 'PT' => 'litros', 'BR' => 'litros', 'MZ' => 'litros', 'AO' => 'litros', ], 'meter' => [ 'PT' => 'metros', 'BR' => 'metros', 'MZ' => 'metros', 'AO' => 'metros', ], ]; $localUnit = $units[$unit][$region] ?? $unit; return $formattedQuantity . ' ' . $localUnit; }}
#Registrar Formatadores Personalizados
Copied!
// app/Providers/AppServiceProvider.phpuse App\Services\CustomLusophoneFormatter; public function register(){ $this->app->singleton('custom.lusophone.formatter', function ($app) { return new CustomLusophoneFormatter(); });} public function boot(){ // Adicionar macro personalizada Str::macro('businessCurrency', function ($amount, $region = null) { return app('custom.lusophone.formatter')->formatBusinessCurrency($amount, $region); }); Str::macro('quantityWithUnit', function ($quantity, $unit, $region = null) { return app('custom.lusophone.formatter')->formatQuantityWithUnit($quantity, $unit, $region); });}
#Usar Formatadores Personalizados
Copied!
use Illuminate\Support\Str; // Usar as macros personalizadasecho Str::businessCurrency(1500.50); // "1.500,50 MT (IVA incluído)"echo Str::quantityWithUnit(25, 'kg'); // "25 kg"echo Str::quantityWithUnit(100.5, 'litre'); // "100,5 litros"
#Formatação para Relatórios
#Relatórios Financeiros
Copied!
// app/Services/FinancialReportService.php<?php namespace App\Services; use ArnaldoTomo\LaravelLusophone\Facades\Lusophone;use Carbon\Carbon; class FinancialReportService{ public function generateMonthlyReport($month, $year) { $region = Lusophone::detectRegion(); $vendas = $this->getVendasMensais($month, $year); $relatorio = [ 'titulo' => $this->getTituloRelatorio($month, $year, $region), 'periodo' => $this->formatarPeriodo($month, $year, $region), 'resumo' => [ 'total_vendas' => Lusophone::formatCurrency($vendas->sum('total'), $region), 'ticket_medio' => Lusophone::formatCurrency($vendas->avg('total'), $region), 'num_transacoes' => Lusophone::formatNumber($vendas->count(), $region), ], 'detalhes' => $vendas->map(function ($venda) use ($region) { return [ 'data' => Lusophone::formatDate($venda->created_at, $region), 'valor' => Lusophone::formatCurrency($venda->total, $region), 'cliente' => $venda->cliente->nome, 'documento_fiscal' => $venda->cliente->documento_fiscal, ]; }), ]; return $relatorio; } private function getTituloRelatorio($month, $year, $region) { $meses = [ 'PT' => ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], 'BR' => ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], 'MZ' => ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro'], ]; $nomesMeses = $meses[$region] ?? $meses['MZ']; $nomeMes = $nomesMeses[$month - 1]; return "Relatório de Vendas - {$nomeMes} {$year}"; } private function formatarPeriodo($month, $year, $region) { $inicio = Carbon::createFromDate($year, $month, 1); $fim = $inicio->copy()->endOfMonth(); return Lusophone::formatDate($inicio, $region) . ' a ' . Lusophone::formatDate($fim, $region); }}
#Export para Excel Localizado
Copied!
// app/Exports/VendasExport.php<?php namespace App\Exports; use Maatwebsite\Excel\Concerns\FromCollection;use Maatwebsite\Excel\Concerns\WithHeadings;use Maatwebsite\Excel\Concerns\WithMapping;use ArnaldoTomo\LaravelLusophone\Facades\Lusophone; class VendasExport implements FromCollection, WithHeadings, WithMapping{ protected $region; public function __construct() { $this->region = Lusophone::detectRegion(); } public function collection() { return Venda::with('cliente')->get(); } public function headings(): array { $headings = [ 'PT' => ['Data', 'Cliente', 'NIF', 'Valor', 'Estado'], 'BR' => ['Data', 'Cliente', 'CPF', 'Valor', 'Status'], 'MZ' => ['Data', 'Cliente', 'NUIT', 'Valor', 'Estado'], 'AO' => ['Data', 'Cliente', 'NIF', 'Valor', 'Estado'], ]; return $headings[$this->region] ?? $headings['MZ']; } public function map($venda): array { return [ Lusophone::formatDate($venda->created_at, $this->region), $venda->cliente->nome, $venda->cliente->documento_fiscal, Lusophone::formatCurrency($venda->total, $this->region), $this->formatarEstado($venda->estado), ]; } private function formatarEstado($estado) { $estados = [ 'PT' => [ 'pending' => 'Pendente', 'paid' => 'Pago', 'cancelled' => 'Cancelado', ], 'BR' => [ 'pending' => 'Pendente', 'paid' => 'Pago', 'cancelled' => 'Cancelado', ], 'MZ' => [ 'pending' => 'Pendente', 'paid' => 'Pago', 'cancelled' => 'Cancelado', ], ]; $estadosRegiao = $estados[$this->region] ?? $estados['MZ']; return $estadosRegiao[$estado] ?? $estado; }}
#Testes de Formatação
#Testes Unitários
Copied!
// tests/Unit/LusophoneFormattingTest.php<?php namespace Tests\Unit; use Tests\TestCase;use ArnaldoTomo\LaravelLusophone\Facades\Lusophone;use Illuminate\Support\Str; class LusophoneFormattingTest extends TestCase{ /** @test */ public function it_formats_currency_for_different_regions() { $testCases = [ 'PT' => ['input' => 1500.50, 'expected' => '1 500,50 €'], 'BR' => ['input' => 1500.50, 'expected' => 'R$ 1.500,50'], 'MZ' => ['input' => 1500.50, 'expected' => '1.500,50 MT'], 'AO' => ['input' => 1500.50, 'expected' => '1.500,50 Kz'], ]; foreach ($testCases as $region => $case) { $formatted = Lusophone::formatCurrency($case['input'], $region); $this->assertEquals($case['expected'], $formatted, "Failed formatting currency for region {$region}"); } } /** @test */ public function it_formats_numbers_correctly() { $number = 1234.56; $this->assertEquals('1.234,56', Lusophone::formatNumber($number, 'MZ')); $this->assertEquals('1 234,56', Lusophone::formatNumber($number, 'PT')); $this->assertEquals('1.234,56', Lusophone::formatNumber($number, 'BR')); } /** @test */ public function str_macros_work_correctly() { Lusophone::forceRegion('MZ'); $this->assertEquals('1.500,50 MT', Str::lusophoneCurrency(1500.50)); $this->assertEquals('1.234,56', Str::lusophoneNumber(1234.56)); $this->assertEquals('15,32%', Str::lusophonePercentage(0.1532)); } /** @test */ public function it_handles_edge_cases() { // Valores zero $this->assertEquals('0,00 MT', Lusophone::formatCurrency(0, 'MZ')); // Valores negativos $this->assertEquals('-1.500,50 MT', Lusophone::formatCurrency(-1500.50, 'MZ')); // Valores muito grandes $this->assertEquals('1.000.000,00 MT', Lusophone::formatCurrency(1000000, 'MZ')); }}
#Testes de Integração
Copied!
// tests/Feature/FormattingIntegrationTest.php<?php namespace Tests\Feature; use Tests\TestCase;use ArnaldoTomo\LaravelLusophone\Facades\Lusophone; class FormattingIntegrationTest extends TestCase{ /** @test */ public function blade_directives_work_in_views() { Lusophone::forceRegion('MZ'); $view = view('test-formatting', ['valor' => 1500.50]); $rendered = $view->render(); $this->assertStringContains('1.500,50 MT', $rendered); } /** @test */ public function api_returns_formatted_values() { Lusophone::forceRegion('PT'); $response = $this->getJson('/api/produtos/1'); $response->assertStatus(200) ->assertJsonPath('produto.preco.formatted', '1 500,50 €'); }}
#Próximos Passos
Agora que domina a formatação no Laravel Lusophone:
- Explore o sistema de traduções
- Configure detecção avançada de região
- Personalize comportamentos
- Prepare para produção
- Integre com sistemas externos
Formatação concluída! 💰 Os seus valores estão agora perfeitamente formatados para qualquer país lusófono.