diff --git a/README.md b/README.md index 24fa8714447a..7bfd991b1d71 100644 --- a/README.md +++ b/README.md @@ -65,4 +65,5 @@ Configure config/database.php and then initialize the database * [mozilla/pdf.js](https://github.com/mozilla/pdf.js) - PDF Reader in JavaScript * [nnnick/Chart.js](https://github.com/nnnick/Chart.js) - Simple HTML5 Charts using the tag * [josscrowcroft/accounting.js](https://github.com/josscrowcroft/accounting.js) - A lightweight JavaScript library for number, money and currency formatting -* [jashkenas/underscore](https://github.com/jashkenas/underscore) - JavaScript's utility _ belt \ No newline at end of file +* [jashkenas/underscore](https://github.com/jashkenas/underscore) - JavaScript's utility _ belt +* [caouecs/Laravel4-long](https://github.com/caouecs/Laravel4-lang) - List of languages ​​for Laravel4 \ No newline at end of file diff --git a/app/config/packages/anahkiasen/former/config.php b/app/config/packages/anahkiasen/former/config.php index a4625318375c..327019638f9d 100755 --- a/app/config/packages/anahkiasen/former/config.php +++ b/app/config/packages/anahkiasen/former/config.php @@ -48,7 +48,7 @@ //////////////////////////////////////////////////////////////////// // Where Former should look for translations - 'translate_from' => 'validation.attributes', + 'translate_from' => 'texts', // An array of attributes to automatically translate 'translatable' => array( diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index 0022b9d0971c..8470e52f0ce1 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -86,7 +86,8 @@ class AccountController extends \BaseController { 'timezones' => Timezone::remember(DEFAULT_QUERY_CACHE)->orderBy('location')->get(), 'dateFormats' => DateFormat::remember(DEFAULT_QUERY_CACHE)->get(), 'datetimeFormats' => DatetimeFormat::remember(DEFAULT_QUERY_CACHE)->get(), - 'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), + 'currencies' => Currency::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), + 'languages' => Language::remember(DEFAULT_QUERY_CACHE)->orderBy('name')->get(), ]; return View::make('accounts.details', $data); @@ -514,7 +515,8 @@ class AccountController extends \BaseController { $account->timezone_id = Input::get('timezone_id') ? Input::get('timezone_id') : null; $account->date_format_id = Input::get('date_format_id') ? Input::get('date_format_id') : null; $account->datetime_format_id = Input::get('datetime_format_id') ? Input::get('datetime_format_id') : null; - $account->currency_id = Input::get('currency_id') ? Input::get('currency_id') : 1; + $account->currency_id = Input::get('currency_id') ? Input::get('currency_id') : 1; // US Dollar + $account->language_id = Input::get('language_id') ? Input::get('language_id') : 1; // English $account->save(); $user = Auth::user(); diff --git a/app/controllers/HomeController.php b/app/controllers/HomeController.php index 459ad6bd2ef8..174ae6721048 100755 --- a/app/controllers/HomeController.php +++ b/app/controllers/HomeController.php @@ -16,22 +16,22 @@ class HomeController extends BaseController { public function showWelcome() { - return View::make('splash'); + return View::make('public.splash'); } public function showAboutUs() { - return View::make('about_us'); + return View::make('public.about_us'); } public function showContactUs() { - return View::make('contact_us'); + return View::make('public.contact_us'); } public function showTerms() { - return View::make('terms'); + return View::make('public.terms'); } public function doContactUs() @@ -46,7 +46,7 @@ class HomeController extends BaseController { 'text' => $message ]; - $this->mailer->sendTo('contact@invoiceninja.com', 'contact@invoiceninja.com', 'Invoice Ninja Feedback', 'contact', $data); + $this->mailer->sendTo(CONTACT_EMAIL, CONTACT_EMAIL, 'Invoice Ninja Feedback', 'contact', $data); Session::flash('message', 'Successfully sent message'); return Redirect::to('/contact'); diff --git a/app/controllers/PaymentController.php b/app/controllers/PaymentController.php index 9d73671cbaf3..af2834da19bc 100755 --- a/app/controllers/PaymentController.php +++ b/app/controllers/PaymentController.php @@ -180,7 +180,15 @@ class PaymentController extends \BaseController $account = $invitation->invoice->client->account; if ($account->isGatewayConfigured(GATEWAY_PAYPAL_EXPRESS)) { - return self::do_payment($invitationKey, false); + if (Session::has('error')) + { + Session::reflash(); + return Redirect::to('view/' . $invitationKey); + } + else + { + return self::do_payment($invitationKey, false); + } } $invitation = Invitation::with('contact', 'invoice.client')->where('invitation_key', '=', $invitationKey)->firstOrFail(); @@ -291,7 +299,7 @@ class PaymentController extends \BaseController $invoice = $invitation->invoice; $accountGateway = $invoice->client->account->account_gateways[0]; - $payment = Payment::createNew(); + $payment = Payment::createNew($invitation); $payment->invitation_id = $invitation->id; $payment->account_gateway_id = $accountGateway->id; $payment->invoice_id = $invoice->id; @@ -334,7 +342,7 @@ class PaymentController extends \BaseController $invoice->invoice_status_id = INVOICE_STATUS_PAID; $invoice->save(); - + Event::fire('invoice.paid', $payment); Session::flash('message', 'Successfully applied payment'); diff --git a/app/controllers/UserController.php b/app/controllers/UserController.php index 91e93febe11f..89d8c7504695 100755 --- a/app/controllers/UserController.php +++ b/app/controllers/UserController.php @@ -249,10 +249,13 @@ class UserController extends BaseController { */ public function logout() { - if (!Auth::user()->registered) + if (Auth::check()) { - $account = Auth::user()->account; - $account->forceDelete(); + if (!Auth::user()->registered) + { + $account = Auth::user()->account; + $account->forceDelete(); + } } Confide::logout(); diff --git a/app/database/migrations/2014_03_19_201454_add_language_support.php b/app/database/migrations/2014_03_19_201454_add_language_support.php new file mode 100644 index 000000000000..5e63292a7d63 --- /dev/null +++ b/app/database/migrations/2014_03_19_201454_add_language_support.php @@ -0,0 +1,56 @@ +increments('id'); + $table->string('name'); + $table->string('locale'); + }); + + DB::table('languages')->insert(['name' => 'English', 'locale' => 'en']); + DB::table('languages')->insert(['name' => 'Italian', 'locale' => 'it']); + DB::table('languages')->insert(['name' => 'German', 'locale' => 'de']); + DB::table('languages')->insert(['name' => 'French', 'locale' => 'fr']); + + Schema::table('accounts', function($table) + { + $table->unsignedInteger('language_id')->default(1); + }); + + DB::table('accounts')->update(['language_id' => 1]); + + Schema::table('accounts', function($table) + { + $table->foreign('language_id')->references('id')->on('languages'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function($table) + { + $table->dropForeign('accounts_language_id_foreign'); + $table->dropColumn('language_id'); + }); + + Schema::drop('languages'); + } + +} diff --git a/app/database/seeds/UserTableSeeder.php b/app/database/seeds/UserTableSeeder.php index 3da62963161b..4250450755d8 100755 --- a/app/database/seeds/UserTableSeeder.php +++ b/app/database/seeds/UserTableSeeder.php @@ -5,21 +5,7 @@ class UserTableSeeder extends Seeder public function run() { - //DB::table('users')->delete(); - /* - $account = Account::create(array( - 'name' => 'Acme Inc', - )); - - $user = User::create(array( - 'account_id' => $account->id, - 'first_name' => 'Hillel', - 'last_name' => 'Coren', - 'email' => 'hillelcoren@gmail.com', - 'password' => Hash::make('1234'), - )); - */ } } \ No newline at end of file diff --git a/app/filters.php b/app/filters.php index 10f66bb40347..1cca8a301718 100755 --- a/app/filters.php +++ b/app/filters.php @@ -20,6 +20,11 @@ App::before(function($request) return Redirect::secure(Request::getRequestUri()); } } + + if (Auth::check()) + { + App::setLocale(Auth::user()->getLocale()); + } }); diff --git a/app/lang/de/pagination.php b/app/lang/de/pagination.php new file mode 100644 index 000000000000..5f83d3e960ee --- /dev/null +++ b/app/lang/de/pagination.php @@ -0,0 +1,20 @@ + '« zurück', + + 'next' => 'weiter »', + +); \ No newline at end of file diff --git a/app/lang/de/reminders.php b/app/lang/de/reminders.php new file mode 100644 index 000000000000..6f0a413e0093 --- /dev/null +++ b/app/lang/de/reminders.php @@ -0,0 +1,24 @@ + "Passwörter müssen 6 Zeichen lang sein und korrekt bestätigt werden.", + + "user" => "Wir konnten leider keinen Nutzer mit dieser E-Mail Adresse finden.", + + "token" => "Der Passwort-Wiederherstellungs-Schlüssel ist ungültig.", + + "sent" => "Passworterinnerung wurde gesendet!", + +); diff --git a/app/lang/de/validation.php b/app/lang/de/validation.php new file mode 100644 index 000000000000..4ceff2e3aada --- /dev/null +++ b/app/lang/de/validation.php @@ -0,0 +1,104 @@ + ":attribute muss akzeptiert werden.", + "active_url" => ":attribute ist keine gültige Internet-Adresse.", + "after" => ":attribute muss ein Datum nach dem :date sein.", + "alpha" => ":attribute darf nur aus Buchstaben bestehen.", + "alpha_dash" => ":attribute darf nur aus Buchstaben, Zahlen, Binde- und Unterstrichen bestehen. Umlaute (ä, ö, ü) und Eszett (ß) sind nicht erlaubt.", + "alpha_num" => ":attribute darf nur aus Buchstaben und Zahlen bestehen.", + "array" => ":attribute muss ein Array sein.", + "before" => ":attribute muss ein Datum vor dem :date sein.", + "between" => array( + "numeric" => ":attribute muss zwischen :min & :max liegen.", + "file" => ":attribute muss zwischen :min & :max Kilobytes groß sein.", + "string" => ":attribute muss zwischen :min & :max Zeichen lang sein.", + "array" => ":attribute muss zwischen :min & :max Elemente haben." + ), + "confirmed" => ":attribute stimmt nicht mit der Bestätigung überein.", + "date" => ":attribute muss ein gültiges Datum sein.", + "date_format" => ":attribute entspricht nicht dem gültigen Format für :format.", + "different" => ":attribute und :other müssen sich unterscheiden.", + "digits" => ":attribute muss :digits Stellen haben.", + "digits_between" => ":attribute muss zwischen :min und :max Stellen haben.", + "email" => ":attribute Format ist ungültig.", + "exists" => "Der gewählte Wert für :attribute ist ungültig.", + "image" => ":attribute muss ein Bild sein.", + "in" => "Der gewählte Wert für :attribute ist ungültig.", + "integer" => ":attribute muss eine ganze Zahl sein.", + "ip" => ":attribute muss eine gültige IP-Adresse sein.", + "max" => array( + "numeric" => ":attribute darf maximal :max sein.", + "file" => ":attribute darf maximal :max Kilobytes groß sein.", + "string" => ":attribute darf maximal :max Zeichen haben.", + "array" => ":attribute darf nicht mehr als :max Elemente haben." + ), + "mimes" => ":attribute muss den Dateityp :values haben.", + "min" => array( + "numeric" => ":attribute muss mindestens :min sein.", + "file" => ":attribute muss mindestens :min Kilobytes groß sein.", + "string" => ":attribute muss mindestens :min Zeichen lang sein.", + "array" => ":attribute muss mindestens :min Elemente haben." + ), + "not_in" => "Der gewählte Wert für :attribute ist ungültig.", + "numeric" => ":attribute muss eine Zahl sein.", + "regex" => ":attribute Format ist ungültig.", + "required" => ":attribute muss ausgefüllt sein.", + "required_if" => ":attribute muss ausgefüllt sein wenn :other :value ist.", + "required_with" => ":attribute muss angegeben werden wenn :values ausgefüllt wurde.", + "required_with_all" => "The :attribute field is required when :values is present.", + "required_without" => ":attribute muss angegeben werden wenn :values nicht ausgefüllt wurde.", + "required_without_all" => ":attribute muss angegeben werden wenn keines der Felder :values ausgefüllt wurde.", + "same" => ":attribute und :other müssen übereinstimmen.", + "size" => array( + "numeric" => ":attribute muss gleich :size sein.", + "file" => ":attribute muss :size Kilobyte groß sein.", + "string" => ":attribute muss :size Zeichen lang sein.", + "array" => ":attribute muss genau :size Elemente haben." + ), + "unique" => ":attribute ist schon vergeben.", + "url" => "Das Format von :attribute ist ungültig.", + + /* + |-------------------------------------------------------------------------- + | Custom Validation Language Lines + |-------------------------------------------------------------------------- + | + | Here you may specify custom validation messages for attributes using the + | convention "attribute.rule" to name the lines. This makes it quick to + | specify a specific custom language line for a given attribute rule. + | + */ + + 'custom' => array( + 'attribute-name' => array( + 'rule-name' => 'custom-message', + ), + ), + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap attribute place-holders + | with something more reader friendly such as E-Mail Address instead + | of "email". This simply helps us make messages a little cleaner. + | + */ + + 'attributes' => array(), + +); diff --git a/app/lang/en/texts.php b/app/lang/en/texts.php new file mode 100644 index 000000000000..97fa8600f494 --- /dev/null +++ b/app/lang/en/texts.php @@ -0,0 +1,28 @@ + 'Organization', + 'name' => 'Name', + 'website' => 'Website', + 'work_phone' => 'Phone', + 'address' => 'Address', + 'address1' => 'Street', + 'address2' => 'Apt/Suite', + 'city' => 'City', + 'state' => 'State/Province', + 'postal_code' => 'Postal Code', + 'country_id' => 'Country', + 'contacts' => 'Contacts', + 'first_name' => 'First Name', + 'last_name' => 'Last Name', + 'phone' => 'Phone', + 'email' => 'Email', + 'additional_info' => 'Additional Info', + 'payment_terms' => 'Payment Terms', + 'currency_id' => 'Currency', + 'size_id' => 'Size', + 'industry_id' => 'Industry', + 'private_notes' => 'Private Notes', + +); \ No newline at end of file diff --git a/app/lang/fr/pagination.php b/app/lang/fr/pagination.php new file mode 100644 index 000000000000..5f0b1d94f7b0 --- /dev/null +++ b/app/lang/fr/pagination.php @@ -0,0 +1,20 @@ + '« Précédent', + + 'next' => 'Suivant »', + +); \ No newline at end of file diff --git a/app/lang/fr/reminders.php b/app/lang/fr/reminders.php new file mode 100644 index 000000000000..e9f1f353e9d8 --- /dev/null +++ b/app/lang/fr/reminders.php @@ -0,0 +1,24 @@ + "Les mots de passe doivent avoir au moins six caractères et doivent être identiques.", + + "user" => "Nous ne pouvons trouver cet utilisateur avec cette adresse e-mail.", + + "token" => "Ce jeton de réinitialisation du mot de passe n'est pas valide.", + + "sent" => "Rappel du mot de passe envoyé !", + +); \ No newline at end of file diff --git a/app/lang/fr/validation.php b/app/lang/fr/validation.php new file mode 100644 index 000000000000..967ffbca1ce1 --- /dev/null +++ b/app/lang/fr/validation.php @@ -0,0 +1,134 @@ + "Le champ :attribute doit être accepté.", + "active_url" => "Le champ :attribute n'est pas une URL valide.", + "after" => "Le champ :attribute doit être une date postérieure au :date.", + "alpha" => "Le champ :attribute doit seulement contenir des lettres.", + "alpha_dash" => "Le champ :attribute doit seulement contenir des lettres, des chiffres et des tirets.", + "alpha_num" => "Le champ :attribute doit seulement contenir des chiffres et des lettres.", + "array" => "Le champ :attribute doit être un tableau.", + "before" => "Le champ :attribute doit être une date antérieure au :date.", + "between" => array( + "numeric" => "La valeur de :attribute doit être comprise entre :min et :max.", + "file" => "Le fichier :attribute doit avoir une taille entre :min et :max kilobytes.", + "string" => "Le texte :attribute doit avoir entre :min et :max caractères.", + "array" => "Le champ :attribute doit avoir entre :min et :max éléments." + ), + "confirmed" => "Le champ de confirmation :attribute ne correspond pas.", + "date" => "Le champ :attribute n'est pas une date valide.", + "date_format" => "Le champ :attribute ne correspond pas au format :format.", + "different" => "Les champs :attribute et :other doivent être différents.", + "digits" => "Le champ :attribute doit avoir :digits chiffres.", + "digits_between" => "Le champ :attribute doit avoir entre :min and :max chiffres.", + "email" => "Le champ :attribute doit être une adresse email valide.", + "exists" => "Le champ :attribute sélectionné est invalide.", + "image" => "Le champ :attribute doit être une image.", + "in" => "Le champ :attribute est invalide.", + "integer" => "Le champ :attribute doit être un entier.", + "ip" => "Le champ :attribute doit être une adresse IP valide.", + "max" => array( + "numeric" => "La valeur de :attribute ne peut être supérieure à :max.", + "file" => "Le fichier :attribute ne peut être plus gros que :max kilobytes.", + "string" => "Le texte de :attribute ne peut contenir plus de :max caractères.", + "array" => "Le champ :attribute ne peut avoir plus de :max éléments.", + ), + "mimes" => "Le champ :attribute doit être un fichier de type : :values.", + "min" => array( + "numeric" => "La valeur de :attribute doit être supérieure à :min.", + "file" => "Le fichier :attribute doit être plus que gros que :min kilobytes.", + "string" => "Le texte :attribute doit contenir au moins :min caractères.", + "array" => "Le champ :attribute doit avoir au moins :min éléments." + ), + "not_in" => "Le champ :attribute sélectionné n'est pas valide.", + "numeric" => "Le champ :attribute doit contenir un nombre.", + "regex" => "Le format du champ :attribute est invalide.", + "required" => "Le champ :attribute est obligatoire.", + "required_if" => "Le champ :attribute est obligatoire quand la valeur de :other est :value.", + "required_with" => "Le champ :attribute est obligatoire quand :values est présent.", + "required_with_all" => "Le champ :attribute est obligatoire quand :values est présent.", + "required_without" => "Le champ :attribute est obligatoire quand :values n'est pas présent.", + "required_without_all" => "Le champ :attribute est requis quand aucun de :values n'est présent.", + "same" => "Les champs :attribute et :other doivent être identiques.", + "size" => array( + "numeric" => "La valeur de :attribute doit être :size.", + "file" => "La taille du fichier de :attribute doit être de :size kilobytes.", + "string" => "Le texte de :attribute doit contenir :size caractères.", + "array" => "Le champ :attribute doit contenir :size éléments." + ), + "unique" => "La valeur du champ :attribute est déjà utilisée.", + "url" => "Le format de l'URL de :attribute n'est pas valide.", + + /* + |-------------------------------------------------------------------------- + | Custom Validation Language Lines + |-------------------------------------------------------------------------- + | + | Here you may specify custom validation messages for attributes using the + | convention "attribute.rule" to name the lines. This makes it quick to + | specify a specific custom language line for a given attribute rule. + | + */ + + 'custom' => array( + 'attribute-name' => array( + 'rule-name' => 'custom-message', + ), + ), + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap attribute place-holders + | with something more reader friendly such as E-Mail Address instead + | of "email". This simply helps us make messages a little cleaner. + | + */ + + 'attributes' => array( + "name" => "Nom", + "username" => "Pseudo", + "email" => "E-mail", + "first_name" => "Prénom", + "last_name" => "Nom", + "password" => "Mot de passe", + "password_confirmation" => "Confirmation du mot de passe", + "city" => "Ville", + "country" => "Pays", + "address" => "Adresse", + "phone" => "Téléphone", + "mobile" => "Portable", + "age" => "Age", + "sex" => "Sexe", + "gender" => "Genre", + "day" => "Jour", + "month" => "Mois", + "year" => "Année", + "hour" => "Heure", + "minute" => "Minute", + "second" => "Seconde", + "title" => "Titre", + "content" => "Contenu", + "description" => "Description", + "excerpt" => "Extrait", + "date" => "Date", + "time" => "Heure", + "available" => "Disponible", + "size" => "Taille" + ), + +); diff --git a/app/lang/it/pagination.php b/app/lang/it/pagination.php new file mode 100644 index 000000000000..f1e10a7b10e1 --- /dev/null +++ b/app/lang/it/pagination.php @@ -0,0 +1,20 @@ + '« Precedente', + + 'next' => 'Successivo »', + +); \ No newline at end of file diff --git a/app/lang/it/reminders.php b/app/lang/it/reminders.php new file mode 100644 index 000000000000..a7ea42a5a159 --- /dev/null +++ b/app/lang/it/reminders.php @@ -0,0 +1,24 @@ + "Le password devono essere di almeno 6 caratteri e devono coincidere.", + + "user" => "Non esiste un utente associato a questo indirizzo e-mail.", + + "token" => "Questo token per la reimpostazione della password non è valido.", + + "sent" => "Promemoria della password inviato!", + +); diff --git a/app/lang/it/validation.php b/app/lang/it/validation.php new file mode 100644 index 000000000000..3d2f8ce2987c --- /dev/null +++ b/app/lang/it/validation.php @@ -0,0 +1,103 @@ + ":attribute deve essere accettato.", + "active_url" => ":attribute non è un URL valido.", + "after" => ":attribute deve essere una data successiva al :date.", + "alpha" => ":attribute può contenere solo lettere.", + "alpha_dash" => ":attribute può contenere solo lettere, numeri e trattini.", + "alpha_num" => ":attribute può contenere solo lettere e numeri.", + "array" => ":attribute deve essere un array.", + "before" => ":attribute deve essere una data precedente al :date.", + "between" => array( + "numeric" => ":attribute deve trovarsi tra :min - :max.", + "file" => ":attribute deve trovarsi tra :min - :max kilobytes.", + "string" => ":attribute deve trovarsi tra :min - :max caratteri.", + "array" => ":attribute deve avere tra :min - :max elementi." + ), + "confirmed" => "Il campo di conferma per :attribute non coincide.", + "date" => ":attribute non è una data valida.", + "date_format" => ":attribute non coincide con il formato :format.", + "different" => ":attribute e :other devono essere differenti.", + "digits" => ":attribute deve essere di :digits cifre.", + "digits_between" => ":attribute deve essere tra :min e :max cifre.", + "email" => ":attribute non è valido.", + "exists" => ":attribute selezionato/a non è valido.", + "image" => ":attribute deve essere un'immagine.", + "in" => ":attribute selezionato non è valido.", + "integer" => ":attribute deve essere intero.", + "ip" => ":attribute deve essere un indirizzo IP valido.", + "max" => array( + "numeric" => ":attribute deve essere minore di :max.", + "file" => ":attribute non deve essere più grande di :max kilobytes.", + "string" => ":attribute non può contenere più di :max caratteri.", + "array" => ":attribute non può avere più di :max elementi." + ), + "mimes" => ":attribute deve essere del tipo: :values.", + "min" => array( + "numeric" => ":attribute deve valere almeno :min.", + "file" => ":attribute deve essere più grande di :min kilobytes.", + "string" => ":attribute deve contenere almeno :min caratteri.", + "array" => ":attribute deve avere almeno :min elementi." + ), + "not_in" => "Il valore selezionato per :attribute non è valido.", + "numeric" => ":attribute deve essere un numero.", + "regex" => "Il formato del campo :attribute non è valido.", + "required" => ":attribute è richiesto.", + "required_if" => "Il campo :attribute è richiesto quando :other è :value.", + "required_with" => "Il campo :attribute è richiesto quando :values è presente.", + "required_with_all" => "The :attribute field is required when :values is present.", + "required_without" => "Il campo :attribute è richiesto quando :values non è presente.", + "required_without_all" => "The :attribute field is required when none of :values are present.", + "same" => ":attribute e :other devono coincidere.", + "size" => array( + "numeric" => ":attribute deve valere :size.", + "file" => ":attribute deve essere grande :size kilobytes.", + "string" => ":attribute deve contenere :size caratteri.", + "array" => ":attribute deve contenere :size elementi." + ), + "unique" => ":attribute è stato già utilizzato.", + "url" => ":attribute deve essere un URL.", + + /* + |-------------------------------------------------------------------------- + | Custom Validation Language Lines + |-------------------------------------------------------------------------- + | + | Here you may specify custom validation messages for attributes using the + | convention "attribute.rule" to name the lines. This makes it quick to + | specify a specific custom language line for a given attribute rule. + | + */ + + 'custom' => array( + 'attribute-name' => array( + 'rule-name' => 'custom-message', + ), + ), + + /* + |-------------------------------------------------------------------------- + | Custom Validation Attributes + |-------------------------------------------------------------------------- + | + | The following language lines are used to swap attribute place-holders + | with something more reader friendly such as E-Mail Address instead + | of "email". This simply helps us make messages a little cleaner. + | + */ + + 'attributes' => array(), + +); diff --git a/app/lang/pt_BR/pagination.php b/app/lang/pt_BR/pagination.php new file mode 100644 index 000000000000..39b1c02096a4 --- /dev/null +++ b/app/lang/pt_BR/pagination.php @@ -0,0 +1,20 @@ + '« Anterior', + +'next' => 'Próximo »', + +); diff --git a/app/lang/pt_BR/reminders.php b/app/lang/pt_BR/reminders.php new file mode 100644 index 000000000000..b1af622faf82 --- /dev/null +++ b/app/lang/pt_BR/reminders.php @@ -0,0 +1,24 @@ + "Senhas devem possuir no mínimo seis caracteres e devem ser iguais.", + +"user" => "Não achamos um usuário com o endereço de e-mail informado.", + +"token" => "Este token de redefinição de senha é inválido.", + +"sent" => "Lmebrete de senha enviado!", + +); diff --git a/app/lang/pt_BR/texts.php b/app/lang/pt_BR/texts.php new file mode 100644 index 000000000000..523f0a85b598 --- /dev/null +++ b/app/lang/pt_BR/texts.php @@ -0,0 +1,28 @@ + 'Organização', + 'name' => 'Nome', + 'website' => 'Website', + 'work_phone' => 'Telefone', + 'address' => 'Endereço', + 'address1' => 'Rua', + 'address2' => 'Bloco/apto', + 'city' => 'Cidade', + 'state' => 'Estado', + 'postal_code' => 'CEP', + 'country_id' => 'País', + 'contacts' => 'Contatos', + 'first_name' => 'Primeiro Nome', + 'last_name' => 'Último Nome', + 'phone' => 'Telefone', + 'email' => 'Email', + 'additional_info' => 'Informações Adicionais', + 'payment_terms' => 'Termos de Pagamento', + 'currency_id' => 'Moeda', + 'size_id' => 'Tamanho', + 'industry_id' => 'Empresa', + 'private_notes' => 'Notas Privadas', + +); diff --git a/app/lang/pt_BR/validation.php b/app/lang/pt_BR/validation.php new file mode 100644 index 000000000000..8123efa69524 --- /dev/null +++ b/app/lang/pt_BR/validation.php @@ -0,0 +1,102 @@ + ":attribute deve ser aceito.", +"active_url" => ":attribute não é uma URL válida.", +"after" => ":attribute deve ser uma data maior que :date.", +"alpha" => ":attribute deve conter apenas letras.", +"alpha_dash" => ":attribute pode conter apenas letras, número e traços", +"alpha_num" => ":attribute pode conter apenas letras e números.", +"array" => ":attribute deve ser um array.", +"before" => ":attribute deve ser uma data anterior a :date.", +"between" => array( +"numeric" => ":attribute deve ser entre :min - :max.", +"file" => ":attribute deve ser entre :min - :max kilobytes.", +"string" => ":attribute deve ser entre :min - :max caracteres.", +"array" => ":attribute deve conter entre :min - :max itens.", +), +"confirmed" => ":attribute confirmação não correponde.", +"date" => ":attribute não é uma data válida.", +"date_format" => ":attribute não satisfaz o formato :format.", +"different" => ":attribute e :other devem ser diferentes.", +"digits" => ":attribute deve conter :digits dígitos.", +"digits_between" => ":attribute deve conter entre :min e :max dígitos.", +"email" => ":attribute está em um formato inválido.", +"exists" => "A opção selecionada :attribute é inválida.", +"image" => ":attribute deve ser uma imagem.", +"in" => "A opção selecionada :attribute é inválida.", +"integer" => ":attribute deve ser um número inteiro.", +"ip" => ":attribute deve ser um endereço IP válido.", +"max" => array( +"numeric" => ":attribute não pode ser maior que :max.", +"file" => ":attribute não pode ser maior que :max kilobytes.", +"string" => ":attribute não pode ser maior que :max caracteres.", +"array" => ":attribute não pode conter mais que :max itens.", +), +"mimes" => ":attribute deve ser um arquivo do tipo: :values.", +"min" => array( +"numeric" => ":attribute não deve ser menor que :min.", +"file" => ":attribute deve ter no mínimo :min kilobytes.", +"string" => ":attribute deve conter no mínimo :min caracteres.", +"array" => ":attribute deve conter ao menos :min itens.", +), +"not_in" => "A opção selecionada :attribute é inválida.", +"numeric" => ":attribute deve ser um número.", +"regex" => ":attribute está em um formato inválido.", +"required" => ":attribute é um campo obrigatório.", +"required_if" => ":attribute é necessário quando :other é :value.", +"required_with" => ":attribute é obrigatório quando :values está presente.", +"required_without" => ":attribute é obrigatório quando :values não está presente.", +"same" => ":attribute e :other devem corresponder.", +"size" => array( +"numeric" => ":attribute deve ter :size.", +"file" => ":attribute deve ter :size kilobytes.", +"string" => ":attribute deve conter :size caracteres.", +"array" => ":attribute deve conter :size itens.", +), +"unique" => ":attribute já está sendo utilizado.", +"url" => ":attribute está num formato inválido.", + +"positive" => ":attribute deve ser maior que zero.", +"has_credit" => "O cliente não possui crédito suficiente.", + + +/* +|-------------------------------------------------------------------------- +| Custom Validation Language Lines +|-------------------------------------------------------------------------- +| +| Here you may specify custom validation messages for attributes using the +| convention "attribute.rule" to name the lines. This makes it quick to +| specify a specific custom language line for a given attribute rule. +| +*/ + +'custom' => array(), + +/* +|-------------------------------------------------------------------------- +| Custom Validation Attributes +|-------------------------------------------------------------------------- +| +| The following language lines are used to swap attribute place-holders +| with something more reader friendly such as E-Mail Address instead +| of "email". This simply helps us make messages a little cleaner. +| +*/ + +'attributes' => array(), + +); diff --git a/app/models/Language.php b/app/models/Language.php new file mode 100755 index 000000000000..182cb510e320 --- /dev/null +++ b/app/models/Language.php @@ -0,0 +1,7 @@ +where('id', '=', $this->account->language_id)->first(); + return $language->locale; + } + public function showGreyBackground() { return !$this->theme_id || in_array($this->theme_id, [2, 3, 5, 6, 7, 8, 10, 11, 12]); } + public function showSignUpPopOver() + { + $count = Session::get(SESSION_COUNTER, 0); + Session::put(SESSION_COUNTER, ++$count); + + return $count == 1 || $count % 7 == 0; + } + public function afterSave($success=true, $forced = false) { if ($this->email) diff --git a/app/routes.php b/app/routes.php index 8f4dfb428b22..332bd03adfdd 100755 --- a/app/routes.php +++ b/app/routes.php @@ -22,37 +22,6 @@ //dd(gethostname()); //Log::error('test'); -/* -Event::listen('illuminate.query', function($query, $bindings, $time, $name) -{ - $data = compact('bindings', 'time', 'name'); - - // Format binding data for sql insertion - foreach ($bindings as $i => $binding) - { - if ($binding instanceof \DateTime) - { - $bindings[$i] = $binding->format('\'Y-m-d H:i:s\''); - } - else if (is_string($binding)) - { - $bindings[$i] = "'$binding'"; - } - } - - // Insert bindings into query - $query = str_replace(array('%', '?'), array('%%', '%s'), $query); - $query = vsprintf($query, $bindings); - - Log::info($query, $data); -}); -*/ - -/* -Route::get('/send_emails', function() { - Artisan::call('ninja:send-invoices'); -}); -*/ Route::get('/', 'HomeController@showWelcome'); Route::get('/rocksteady', 'HomeController@showWelcome'); @@ -167,7 +136,9 @@ HTML::macro('breadcrumbs', function() { // Get the breadcrumbs by exploding the current path. $basePath = Utils::basePath(); - $path = $_SERVER['REQUEST_URI']; + $parts = explode('?', $_SERVER['REQUEST_URI']); + $path = $parts[0]; + if ($basePath != '/') { $path = str_replace($basePath, '', $path); @@ -200,7 +171,9 @@ HTML::macro('breadcrumbs', function() { return $str . ''; }); + define('CONTACT_EMAIL', 'contact@invoiceninja.com'); +define('ANALYTICS_KEY', 'UA-46031341-1'); define('ENV_DEVELOPMENT', 'local'); define('ENV_STAGING', 'staging'); @@ -250,13 +223,14 @@ define('SESSION_CURRENCY', 'currency'); define('SESSION_DATE_FORMAT', 'dateFormat'); define('SESSION_DATE_PICKER_FORMAT', 'datePickerFormat'); define('SESSION_DATETIME_FORMAT', 'datetimeFormat'); +define('SESSION_COUNTER', 'sessionCounter'); define('DEFAULT_TIMEZONE', 'US/Eastern'); define('DEFAULT_CURRENCY', 1); // US Dollar define('DEFAULT_DATE_FORMAT', 'M j, Y'); define('DEFAULT_DATE_PICKER_FORMAT', 'M d, yyyy'); define('DEFAULT_DATETIME_FORMAT', 'F j, Y, g:i a'); -define('DEFAULT_QUERY_CACHE', 120); +define('DEFAULT_QUERY_CACHE', 120); // minutes define('GATEWAY_PAYPAL_EXPRESS', 17); @@ -266,7 +240,6 @@ if (Auth::check() && !Session::has(SESSION_TIMEZONE)) Event::fire('user.refresh'); } - Validator::extend('positive', function($attribute, $value, $parameters) { return Utils::parseFloat($value) > 0; @@ -281,4 +254,31 @@ Validator::extend('has_credit', function($attribute, $value, $parameters) $credit = $client->getTotalCredit(); return $credit >= $amount; -}); \ No newline at end of file +}); + + +/* +Event::listen('illuminate.query', function($query, $bindings, $time, $name) +{ + $data = compact('bindings', 'time', 'name'); + + // Format binding data for sql insertion + foreach ($bindings as $i => $binding) + { + if ($binding instanceof \DateTime) + { + $bindings[$i] = $binding->format('\'Y-m-d H:i:s\''); + } + else if (is_string($binding)) + { + $bindings[$i] = "'$binding'"; + } + } + + // Insert bindings into query + $query = str_replace(array('%', '?'), array('%%', '%s'), $query); + $query = vsprintf($query, $bindings); + + Log::info($query, $data); +}); +*/ \ No newline at end of file diff --git a/app/views/about_us.blade.php b/app/views/about_us.blade.php deleted file mode 100644 index 68caa700259a..000000000000 --- a/app/views/about_us.blade.php +++ /dev/null @@ -1,170 +0,0 @@ -@extends('master') - -@section('head') - - - - - -@stop - -@section('body') - -{{ Form::open(array('url' => 'get_started', 'id' => 'startForm')) }} -{{ Form::hidden('guest_key') }} -{{ Form::close() }} - - - - - -
-
-
-

WHY INVOICE NINJA? -

-
-
-
- -
-
-
-
-

Open Source Platform

-

Free yourself from online invoicing platforms with high monthly fees and limited functionality. Being open source allows us fast app development, security audits by the open-course community, and we can keep it FREE!

-
-
-
-
- -
-
-
-
-
- -
-
-
-

Live PDF Creation

-

Look professional from day #1. Select one of our beautiful invoice templates to suit your company identity, switch between designs in real time to preview invoices & email them to clients with one click. The live preview PDF function was designed for an efficient and hassle-free experience, and it’s awesome! -

-
-
-
-
-
-
-
-
-

Online Payments

-

Authorize.net, Beanstream, PayPal? InvoiceNinja supports the most popular online payment gateways! If you need help integrating a third party gateway we don’t yet support, please contact us! We’re happy to help! If you need assistance of want to learn more about online payment solutions, contact us!

-
-
-
- -
-
-
-
-
- - - - - - @stop \ No newline at end of file diff --git a/app/views/accounts/details.blade.php b/app/views/accounts/details.blade.php index 74f6aa8ae1b7..bf8df2a95763 100755 --- a/app/views/accounts/details.blade.php +++ b/app/views/accounts/details.blade.php @@ -62,8 +62,9 @@ {{ Former::text('email') }} {{ Former::text('phone') }} - {{ Former::legend('Localization') }} + {{ Former::select('language_id')->addOption('','')->label('Language') + ->fromQuery($languages, 'name', 'id') }} {{ Former::select('currency_id')->addOption('','')->label('Currency') ->fromQuery($currencies, 'name', 'id') }} {{ Former::select('timezone_id')->addOption('','')->label('Timezone') diff --git a/app/views/accounts/payments.blade.php b/app/views/accounts/payments.blade.php index eb17821f213d..c289d8829fa9 100755 --- a/app/views/accounts/payments.blade.php +++ b/app/views/accounts/payments.blade.php @@ -14,10 +14,8 @@ @if ($accountGateway) {{ Former::populateField('gateway_id', $accountGateway->gateway_id) }} @foreach ($accountGateway->fields as $field => $junk) - @if ($field == 'testMode' || $field == 'developerMode') - @if ($config->$field) - {{-- Former::populateField($accountGateway->gateway_id.'_'.$field, true ) --}} - @endif + @if (in_array($field, ['solutionType', 'landingPage', 'headerImageUrl', 'brandName'])) + {{-- do nothing --}} @else {{ Former::populateField($accountGateway->gateway_id.'_'.$field, $config->$field) }} @endif diff --git a/app/views/clients/edit.blade.php b/app/views/clients/edit.blade.php index 2da0e44a076e..75c976d05f94 100755 --- a/app/views/clients/edit.blade.php +++ b/app/views/clients/edit.blade.php @@ -21,26 +21,26 @@
- {{ Former::legend('Organization') }} + {{ Former::legend('organization') }} {{ Former::text('name')->data_bind("attr { placeholder: placeholderName }") }} {{ Former::text('website') }} - {{ Former::text('work_phone')->label('Phone') }} + {{ Former::text('work_phone') }} - {{ Former::legend('Address') }} - {{ Former::text('address1')->label('Street') }} - {{ Former::text('address2')->label('Apt/Suite') }} + {{ Former::legend('address') }} + {{ Former::text('address1') }} + {{ Former::text('address2') }} {{ Former::text('city') }} - {{ Former::text('state')->label('State/Province') }} + {{ Former::text('state') }} {{ Former::text('postal_code') }} - {{ Former::select('country_id')->addOption('','')->label('Country') + {{ Former::select('country_id')->addOption('','') ->fromQuery($countries, 'name', 'id') }}
- {{ Former::legend('Contacts') }} + {{ Former::legend('contacts') }}
@@ -62,14 +62,14 @@
- {{ Former::legend('Additional Info') }} + {{ Former::legend('additional_info') }} {{ Former::select('payment_terms')->addOption('','') ->fromQuery($paymentTerms, 'name', 'num_days') }} - {{ Former::select('currency_id')->addOption('','')->label('Currency') + {{ Former::select('currency_id')->addOption('','') ->fromQuery($currencies, 'name', 'id') }} - {{ Former::select('size_id')->addOption('','')->label('Size') + {{ Former::select('size_id')->addOption('','') ->fromQuery($sizes, 'name', 'id') }} - {{ Former::select('industry_id')->addOption('','')->label('Industry') + {{ Former::select('industry_id')->addOption('','') ->fromQuery($industries, 'name', 'id') }} {{ Former::textarea('private_notes') }} diff --git a/app/views/contact_us.blade.php b/app/views/contact_us.blade.php deleted file mode 100644 index 1405c8c54bab..000000000000 --- a/app/views/contact_us.blade.php +++ /dev/null @@ -1,216 +0,0 @@ -@extends('master') - -@section('head') - - - - - - -@stop - -@section('body') - -{{ Form::open(array('url' => 'get_started', 'id' => 'startForm')) }} -{{ Form::hidden('guest_key') }} -{{ Form::close() }} - - - - - -
-
-
-

Contact us -

-
-
-
- -
-
-
- - - @if (Session::has('message')) -
{{ Session::get('message') }}
- @endif - - @if (Session::has('error')) -
{{ Session::get('error') }}
- @endif - - -
-
-

Questions, special requests, or just want to say hi?

-

Fill in the form below and we'll get back to you as soon as possible. Hope to hear from you!

- - {{ Form::open(['url' => 'contact', 'class' => 'feedbackForm']) }} -
- - -
-
- - -
-
- - -
-
-
- -
-
- - {{ Form::close() }} - -
-
-

Other ways to reach us

-

contact@invoiceninja.com

-

+1-800-763-1948

-

- -
-
-
-
- -
- - - - - - - - -@stop \ No newline at end of file diff --git a/app/views/header.blade.php b/app/views/header.blade.php index 95c32ffd068a..ff130b570153 100755 --- a/app/views/header.blade.php +++ b/app/views/header.blade.php @@ -94,6 +94,22 @@ + + + + + + + +@stop \ No newline at end of file diff --git a/app/views/public/header.blade.php b/app/views/public/header.blade.php new file mode 100644 index 000000000000..5a47e2290ddf --- /dev/null +++ b/app/views/public/header.blade.php @@ -0,0 +1,112 @@ +@extends('master') + +@section('head') + + + + + + +@stop + +@section('body') + +
+ + + +{{ Form::open(array('url' => 'get_started', 'id' => 'startForm')) }} +{{ Form::hidden('guest_key') }} +{{ Form::close() }} + + + + + + + + @yield('content') + + + + + + + +@stop \ No newline at end of file diff --git a/app/views/public/splash.blade.php b/app/views/public/splash.blade.php new file mode 100755 index 000000000000..2a520e2e525c --- /dev/null +++ b/app/views/public/splash.blade.php @@ -0,0 +1,113 @@ +@extends('public.header') + +@section('content') + + +
+
+ +
+
+
+
+

THE SIMPLE & + FREE WAY TO INVOICE + CLIENTS

+

It's that easy. Stop spending time on + complicated and expensive invoicing.
+ No fuss, just get started and get paid.

+
+
+
+
+ + +
+ +
+
+
+
+
+
+

100% FREE, ALWAYS

+

Invoicing with no monthly fee, because you have enough bills already! Free, now and forever! Quality invoicing to build your business and get paid.

+
+
+ +
+
+
+

OPEN-SOURCE

+

Cloud-based, super secure, and user-developed. Open source platforms are a better way to do business (and save the world). Need we say more?

+
+
+ +
+
+
+

LIVE .PDF VIEW

+

Create beautiful email-ready .PDF invoices created instantly as you type. Our ‘Save & send’ feature saves you time and impresses clients.

+
+
+ +
+
+
+

ONLINE PAYMENTS

+

PayPal? Authorize.Net? Stripe? We support many payment technologies and if you need help or advice we’ll lend a hand (we’re pretty friendly).

+
+
+
+
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+

SIMPLE, INTUITIVE INVOICING.

+
+
+
+ + + + @stop \ No newline at end of file diff --git a/app/views/terms.blade.php b/app/views/public/terms.blade.php similarity index 72% rename from app/views/terms.blade.php rename to app/views/public/terms.blade.php index 1e3439714308..44776fa9fabf 100644 --- a/app/views/terms.blade.php +++ b/app/views/public/terms.blade.php @@ -1,29 +1,6 @@ -@extends('master') +@extends('public.header') -@section('head') - - - - - -@stop - -@section('body') - - - +@section('content')
@@ -170,41 +147,4 @@

 

 

- -
- -
- - @stop \ No newline at end of file +@stop \ No newline at end of file diff --git a/app/views/splash.blade.php b/app/views/splash.blade.php deleted file mode 100755 index a9700183b435..000000000000 --- a/app/views/splash.blade.php +++ /dev/null @@ -1,196 +0,0 @@ -@extends('master') - -@section('head') - - - - - -@stop - -@section('body') - -{{ Form::open(array('url' => 'get_started', 'id' => 'startForm')) }} -{{ Form::hidden('guest_key') }} -{{ Form::close() }} - - - - - -
-
- -
-
-
-
-

THE SIMPLE & - FREE WAY TO INVOICE - CLIENTS

-

It's that easy. Stop spending time on - complicated and expensive invoicing.
- No fuss, just get started and get paid.

-
-
-
-
- - -
- -
-
-
-
-
-
-

100% FREE, ALWAYS

-

Invoicing with no monthly fee, because you have enough bills already! Free, now and forever! Quality invoicing to build your business and get paid.

-
-
- -
-
-
-

OPEN-SOURCE

-

Cloud-based, super secure, and user-developed. Open source platforms are a better way to do business (and save the world). Need we say more?

-
-
- -
-
-
-

LIVE .PDF VIEW

-

Create beautiful email-ready .PDF invoices created instantly as you type. Our ‘Save & send’ feature saves you time and impresses clients.

-
-
- -
-
-
-

ONLINE PAYMENTS

-

PayPal? Authorize.Net? Stripe? We support many payment technologies and if you need help or advice we’ll lend a hand (we’re pretty friendly).

-
-
-
-
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
-
-

SIMPLE, INTUITIVE INVOICING.

-
-
-
- - - -
- -
- - - @stop \ No newline at end of file diff --git a/public/css/style.css b/public/css/style.css index a730b6a6927a..f43a14529731 100755 --- a/public/css/style.css +++ b/public/css/style.css @@ -616,6 +616,9 @@ color: #fff; background-color: #08273c; border-color: #08273c; } +#signUpPopOver { + cursor: pointer; +} @media (max-width: 767px) { .navbar-default .navbar-nav .open .dropdown-menu > li > a { color: #ecf0f1; diff --git a/public/images/facebook.jpg b/public/images/facebook.jpg index 83fe17e4380a..9770a82ccf58 100644 Binary files a/public/images/facebook.jpg and b/public/images/facebook.jpg differ