├── .env.example ├── .github └── workflows │ └── tests.yml ├── .gitignore ├── DOCUMENTATION.md ├── README.md ├── composer.json ├── config └── seo-pro.php ├── content └── seo.yaml ├── package-lock.json ├── package.json ├── phpunit.xml ├── pint.json ├── resources ├── css │ └── cp.css ├── dist │ ├── build │ │ ├── assets │ │ │ ├── cp-3890d5e1.js │ │ │ ├── cp-56146771.css │ │ │ └── cp-7025c2cd.css │ │ └── manifest.json │ ├── js │ │ └── cp.js │ └── mix-manifest.json ├── js │ ├── components │ │ ├── fieldtypes │ │ │ ├── SeoProFieldtype.vue │ │ │ └── SourceFieldtype.vue │ │ └── reporting │ │ │ ├── IndexScore.vue │ │ │ ├── PageDetails.vue │ │ │ ├── RelativeDate.vue │ │ │ ├── Report.vue │ │ │ └── StatusIcon.vue │ └── cp.js ├── lang │ ├── da │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ ├── de │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ ├── de_CH │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ ├── en │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ ├── es │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ ├── fr │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ ├── it │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ ├── nl │ │ ├── fieldsets │ │ │ ├── content.php │ │ │ ├── defaults.php │ │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php │ └── pt │ │ ├── fieldsets │ │ ├── content.php │ │ ├── defaults.php │ │ └── sections.php │ │ ├── messages.php │ │ └── settings.php ├── svg │ └── seo-reports.svg └── views │ ├── edit.blade.php │ ├── generated │ ├── humans.antlers.html │ ├── sitemap.antlers.html │ └── sitemap_index.antlers.html │ ├── index.blade.php │ ├── meta.antlers.html │ ├── reports │ ├── create.blade.php │ ├── index.blade.php │ └── show.blade.php │ ├── sections.blade.php │ └── widget.blade.php ├── routes ├── cp.php └── web.php ├── src ├── Blueprint.php ├── Cascade.php ├── Commands │ └── GenerateReportCommand.php ├── Directives │ └── SeoProDirective.php ├── Events │ └── SeoProSiteDefaultsSaved.php ├── Fields.php ├── Fieldtypes │ ├── Rules │ │ └── SourceFieldRule.php │ ├── SeoProFieldtype.php │ └── SourceFieldtype.php ├── GetsSectionDefaults.php ├── GraphQL │ ├── AlternateLocaleType.php │ └── SeoProType.php ├── HasAssetField.php ├── Http │ └── Controllers │ │ ├── CollectionDefaultsController.php │ │ ├── HumansController.php │ │ ├── ReportController.php │ │ ├── ReportPagesController.php │ │ ├── SectionDefaultsController.php │ │ ├── SiteDefaultsController.php │ │ ├── SitemapController.php │ │ └── TaxonomyDefaultsController.php ├── NullModel.php ├── RendersMetaHtml.php ├── Reporting │ ├── Chunk.php │ ├── Page.php │ ├── Report.php │ ├── Rule.php │ └── Rules │ │ ├── Concerns │ │ ├── FailsWhenPagesDontPass.php │ │ └── WarnsWhenPagesDontPass.php │ │ ├── NoUnderscoresInUrl.php │ │ ├── SiteName.php │ │ ├── ThreeSegmentUrls.php │ │ ├── UniqueMetaDescription.php │ │ └── UniqueTitleTag.php ├── ServiceProvider.php ├── SiteDefaults.php ├── Sitemap │ ├── Page.php │ └── Sitemap.php ├── Subscriber.php ├── Tags │ └── SeoProTags.php └── Widgets │ └── SeoProWidget.php ├── tests ├── CascadeTest.php ├── Fixtures │ ├── site-localized │ │ ├── assets │ │ │ └── img │ │ │ │ ├── coffee-mug.jpg │ │ │ │ └── stetson.jpg │ │ ├── config │ │ │ ├── filesystems.php │ │ │ └── statamic │ │ │ │ ├── stache.php │ │ │ │ └── users.php │ │ ├── content │ │ │ ├── assets │ │ │ │ ├── .gitkeep │ │ │ │ └── assets.yaml │ │ │ ├── collections │ │ │ │ ├── .gitkeep │ │ │ │ ├── articles.yaml │ │ │ │ ├── articles │ │ │ │ │ ├── default │ │ │ │ │ │ ├── 1994-07-05.magic.md │ │ │ │ │ │ ├── 1996-08-16.nectar.md │ │ │ │ │ │ └── 1996-11-18.dance.md │ │ │ │ │ └── french │ │ │ │ │ │ └── 1996-08-16.nectar.md │ │ │ │ ├── pages.yaml │ │ │ │ └── pages │ │ │ │ │ ├── british │ │ │ │ │ └── home.md │ │ │ │ │ ├── default │ │ │ │ │ ├── about.md │ │ │ │ │ ├── articles.md │ │ │ │ │ ├── home.md │ │ │ │ │ └── topics.md │ │ │ │ │ ├── french │ │ │ │ │ ├── about.md │ │ │ │ │ └── home.md │ │ │ │ │ └── italian │ │ │ │ │ ├── about.md │ │ │ │ │ └── home.md │ │ │ ├── globals │ │ │ │ ├── .gitkeep │ │ │ │ ├── default │ │ │ │ │ └── settings.yaml │ │ │ │ ├── french │ │ │ │ │ └── settings.yaml │ │ │ │ └── settings.yaml │ │ │ ├── navigation │ │ │ │ └── .gitkeep │ │ │ ├── taxonomies │ │ │ │ ├── .gitkeep │ │ │ │ ├── topics.yaml │ │ │ │ └── topics │ │ │ │ │ ├── dance.yaml │ │ │ │ │ ├── sneakers.yaml │ │ │ │ │ └── soda.yaml │ │ │ └── trees │ │ │ │ └── collections │ │ │ │ ├── british │ │ │ │ └── pages.yaml │ │ │ │ ├── default │ │ │ │ └── pages.yaml │ │ │ │ ├── french │ │ │ │ └── pages.yaml │ │ │ │ └── italian │ │ │ │ └── pages.yaml │ │ └── resources │ │ │ └── sites.yaml │ ├── site │ │ ├── assets │ │ │ └── img │ │ │ │ ├── coffee-mug.jpg │ │ │ │ └── stetson.jpg │ │ ├── config │ │ │ ├── filesystems.php │ │ │ └── statamic │ │ │ │ ├── stache.php │ │ │ │ └── users.php │ │ ├── content │ │ │ ├── assets │ │ │ │ ├── .gitkeep │ │ │ │ └── assets.yaml │ │ │ ├── collections │ │ │ │ ├── .gitkeep │ │ │ │ ├── articles.yaml │ │ │ │ ├── articles │ │ │ │ │ ├── 1994-07-05.magic.md │ │ │ │ │ ├── 1996-08-16.nectar.md │ │ │ │ │ └── 1996-11-18.dance.md │ │ │ │ ├── pages.yaml │ │ │ │ └── pages │ │ │ │ │ ├── about.md │ │ │ │ │ ├── articles.md │ │ │ │ │ ├── home.md │ │ │ │ │ └── topics.md │ │ │ ├── globals │ │ │ │ ├── .gitkeep │ │ │ │ └── settings.yaml │ │ │ ├── navigation │ │ │ │ └── .gitkeep │ │ │ ├── taxonomies │ │ │ │ ├── .gitkeep │ │ │ │ ├── topics.yaml │ │ │ │ └── topics │ │ │ │ │ ├── dance.yaml │ │ │ │ │ ├── sneakers.yaml │ │ │ │ │ └── soda.yaml │ │ │ └── trees │ │ │ │ └── collections │ │ │ │ └── pages.yaml │ │ └── resources │ │ │ └── sites.yaml │ └── views │ │ ├── antlers │ │ ├── errors │ │ │ └── 404.antlers.html │ │ ├── layout.antlers.html │ │ └── page.antlers.html │ │ ├── blade-components │ │ ├── components │ │ │ └── layout.blade.php │ │ ├── errors │ │ │ └── 404.blade.php │ │ └── page.blade.php │ │ └── blade │ │ ├── errors │ │ └── 404.blade.php │ │ ├── layout.blade.php │ │ └── page.blade.php ├── GraphQLTest.php ├── HumansTest.php ├── Localized │ ├── CascadeTest.php │ ├── GraphQLTest.php │ └── MetaTagTest.php ├── MetaTagTest.php ├── ReportTest.php ├── SitemapTest.php ├── TestCase.php └── ViewScenarios.php └── vite.config.js /.env.example: -------------------------------------------------------------------------------- 1 | STATAMIC_PATH=/path/to/statamic/app/ 2 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Run Tests 2 | 3 | on: 4 | push: 5 | pull_request: 6 | schedule: 7 | - cron: '0 0 * * *' 8 | 9 | jobs: 10 | php-tests: 11 | runs-on: ${{ matrix.os }} 12 | if: "!contains(github.event.head_commit.message, '[ci skip]')" 13 | 14 | strategy: 15 | matrix: 16 | php: [8.1, 8.2, 8.3, 8.4] 17 | laravel: [10.*, 11.*, 12.*] 18 | stability: [prefer-lowest, prefer-stable] 19 | os: [ubuntu-latest] 20 | include: 21 | - os: windows-latest 22 | php: 8.3 23 | laravel: 10.* 24 | stability: prefer-stable 25 | - os: windows-latest 26 | php: 8.3 27 | laravel: 11.* 28 | stability: prefer-stable 29 | - os: windows-latest 30 | php: 8.4 31 | laravel: 11.* 32 | stability: prefer-stable 33 | exclude: 34 | - php: 8.1 35 | laravel: 11.* 36 | - php: 8.1 37 | laravel: 12.* 38 | - php: 8.4 39 | laravel: 10.* 40 | 41 | name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} 42 | 43 | steps: 44 | - name: Checkout code 45 | uses: actions/checkout@v1 46 | 47 | - name: Setup PHP 48 | uses: shivammathur/setup-php@v2 49 | with: 50 | php-version: ${{ matrix.php }} 51 | extensions: dom, curl, libxml, mbstring, zip, pcntl, pdo, sqlite, pdo_sqlite, bcmath, soap, intl, gd, exif, iconv, imagick, fileinfo 52 | coverage: none 53 | 54 | - name: Install dependencies 55 | run: | 56 | composer require "illuminate/contracts:${{ matrix.laravel }}" --no-interaction --no-update 57 | composer update --${{ matrix.stability }} --prefer-dist --no-interaction --no-suggest 58 | 59 | - name: Execute tests 60 | run: vendor/bin/phpunit 61 | 62 | - name: Send Slack notification 63 | uses: 8398a7/action-slack@v2 64 | if: failure() && github.event_name == 'schedule' 65 | with: 66 | status: ${{ job.status }} 67 | author_name: ${{ github.actor }} 68 | env: 69 | SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} 70 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 71 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | .env 4 | composer.lock 5 | /vendor 6 | .phpunit.result.cache 7 | .phpunit.cache 8 | .idea/ 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SEO Pro 2 | 3 | ![Statamic 3.0+](https://img.shields.io/badge/Statamic-3.0+-FF269E?style=for-the-badge&link=https://statamic.com) 4 | 5 | > SEO Pro is an all-in-one site reporting, metadata wrangling, Open Graph managing, Twitter card making, sitemap generating, turnkey addon. 6 | 7 | ## SEO Pro is a Commercial Addon. 8 | 9 | You can use it for free while in development, but requires a license to use on a live site. Learn more or buy a license on [The Statamic Marketplace](https://statamic.com/addons/statamic/seo-pro)! 10 | 11 | ## Documentation 12 | 13 | Read the docs on the [Statamic Marketplace](https://statamic.com/addons/statamic/seo-pro/docs) or contribute to it [here on GitHub](DOCUMENTATION.md). 14 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "statamic/seo-pro", 3 | "autoload": { 4 | "psr-4": { 5 | "Statamic\\SeoPro\\": "src" 6 | } 7 | }, 8 | "autoload-dev": { 9 | "psr-4": { 10 | "Tests\\": "tests" 11 | } 12 | }, 13 | "extra": { 14 | "statamic": { 15 | "name": "SEO Pro", 16 | "description": "An all-in-one site reporting, metadata mastering, OG managing, Twitter card making, sitemap generating addon." 17 | }, 18 | "laravel": { 19 | "providers": [ 20 | "Statamic\\SeoPro\\ServiceProvider" 21 | ] 22 | } 23 | }, 24 | "require": { 25 | "statamic/cms": "^5.45.1" 26 | }, 27 | "require-dev": { 28 | "orchestra/testbench": "^8.28 || ^9.6.1 || ^10.0", 29 | "phpunit/phpunit": "^10.5.35 || ^11.0", 30 | "laravel/pint": "^1.17" 31 | }, 32 | "config": { 33 | "allow-plugins": { 34 | "pixelfear/composer-dist-plugin": true 35 | } 36 | }, 37 | "minimum-stability": "dev", 38 | "prefer-stable": true 39 | } 40 | -------------------------------------------------------------------------------- /config/seo-pro.php: -------------------------------------------------------------------------------- 1 | [ 6 | 'path' => base_path('content/seo.yaml'), 7 | ], 8 | 9 | 'assets' => [ 10 | 'container' => null, 11 | 'twitter_preset' => [ 12 | 'w' => 1200, 13 | 'h' => 600, 14 | ], 15 | 'open_graph_preset' => [ 16 | 'w' => 1146, 17 | 'h' => 600, 18 | ], 19 | ], 20 | 21 | 'sitemap' => [ 22 | 'enabled' => true, 23 | 'url' => 'sitemap.xml', 24 | 'expire' => 60, 25 | 'pagination' => [ 26 | 'enabled' => false, 27 | 'url' => 'sitemap_{page}.xml', 28 | 'limit' => 100, 29 | ], 30 | ], 31 | 32 | 'humans' => [ 33 | 'enabled' => true, 34 | 'url' => 'humans.txt', 35 | ], 36 | 37 | 'pagination' => [ 38 | 'enabled_in_canonical_url' => true, 39 | 'enabled_on_first_page' => false, 40 | ], 41 | 42 | 'twitter' => [ 43 | 'card' => 'summary_large_image', 44 | ], 45 | 46 | 'alternate_locales' => [ 47 | 'enabled' => true, 48 | 'excluded_sites' => [], 49 | ], 50 | 51 | 'reports' => [ 52 | 'keep_recent' => 'all', 53 | 'queue_chunk_size' => 1000, 54 | ], 55 | 56 | ]; 57 | -------------------------------------------------------------------------------- /content/seo.yaml: -------------------------------------------------------------------------------- 1 | site_name: Site Name 2 | site_name_position: after 3 | site_name_separator: '|' 4 | title: '@seo:title' 5 | description: '@seo:content' 6 | canonical_url: '@seo:permalink' 7 | priority: 0.5 8 | change_frequency: monthly 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "rm -rf resources/dist/build && vite", 5 | "build": "vite build" 6 | }, 7 | "dependencies": { 8 | "cross-env": "^7.0.2", 9 | "underscore": "~1.12.1", 10 | "vue": "^2.6.11" 11 | }, 12 | "devDependencies": { 13 | "@vitejs/plugin-vue2": "^2.2.0", 14 | "laravel-vite-plugin": "^0.7.2", 15 | "vite": "^4.5.14" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ./tests 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | ./src 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "laravel", 3 | "rules": { 4 | "binary_operator_spaces": { 5 | "default": "single_space", 6 | "operators": { 7 | "=>": null 8 | } 9 | }, 10 | "class_attributes_separation": { 11 | "elements": { 12 | "method": "one" 13 | } 14 | }, 15 | "class_definition": { 16 | "multi_line_extends_each_single_line": true, 17 | "single_item_single_line": true 18 | }, 19 | "psr_autoloading": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /resources/css/cp.css: -------------------------------------------------------------------------------- 1 | .bg-yellow-dark { 2 | background-color: #f6ad55; 3 | } 4 | 5 | .text-red-800 { 6 | color: rgb(153 27 27); 7 | } 8 | -------------------------------------------------------------------------------- /resources/dist/build/assets/cp-56146771.css: -------------------------------------------------------------------------------- 1 | .seo_pro-fieldtype>.field-inner>label{display:none!important}.seo_pro-fieldtype,.seo_pro-fieldtype .publish-fields{padding:0!important}.source-type-select{width:20rem}.inherit-placeholder{padding-top:5px}.source-field-select .selectize-dropdown,.source-field-select .selectize-input span{font-family:Menlo,Monaco,Consolas,Liberation Mono,Courier New,"monospace";font-size:12px} 2 | -------------------------------------------------------------------------------- /resources/dist/build/assets/cp-7025c2cd.css: -------------------------------------------------------------------------------- 1 | .bg-yellow-dark{background-color:#f6ad55}.text-red-800{color:#991b1b} 2 | -------------------------------------------------------------------------------- /resources/dist/build/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources/css/cp.css": { 3 | "file": "assets/cp-7025c2cd.css", 4 | "isEntry": true, 5 | "src": "resources/css/cp.css" 6 | }, 7 | "resources/js/cp.css": { 8 | "file": "assets/cp-56146771.css", 9 | "src": "resources/js/cp.css" 10 | }, 11 | "resources/js/cp.js": { 12 | "css": [ 13 | "assets/cp-56146771.css" 14 | ], 15 | "file": "assets/cp-3890d5e1.js", 16 | "isEntry": true, 17 | "src": "resources/js/cp.js" 18 | } 19 | } -------------------------------------------------------------------------------- /resources/dist/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/cp.js": "/js/cp.js" 3 | } 4 | -------------------------------------------------------------------------------- /resources/js/components/fieldtypes/SeoProFieldtype.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 30 | 31 | 80 | -------------------------------------------------------------------------------- /resources/js/components/reporting/IndexScore.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 67 | -------------------------------------------------------------------------------- /resources/js/components/reporting/PageDetails.vue: -------------------------------------------------------------------------------- 1 | 2 | 33 | 34 | 35 | 46 | -------------------------------------------------------------------------------- /resources/js/components/reporting/RelativeDate.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 35 | -------------------------------------------------------------------------------- /resources/js/components/reporting/StatusIcon.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 28 | -------------------------------------------------------------------------------- /resources/js/cp.js: -------------------------------------------------------------------------------- 1 | import SeoProFieldtype from './components/fieldtypes/SeoProFieldtype.vue'; 2 | import SourceFieldtype from './components/fieldtypes/SourceFieldtype.vue'; 3 | import StatusIcon from './components/reporting/StatusIcon.vue'; 4 | import IndexScore from './components/reporting/IndexScore.vue'; 5 | import Report from './components/reporting/Report.vue'; 6 | 7 | Statamic.$components.register('seo_pro-fieldtype', SeoProFieldtype); 8 | Statamic.$components.register('seo_pro_source-fieldtype', SourceFieldtype); 9 | 10 | Statamic.$components.register('seo-pro-status-icon', StatusIcon); 11 | Statamic.$components.register('seo-pro-report', Report); 12 | Statamic.$components.register('seo-pro-index-score', IndexScore); 13 | -------------------------------------------------------------------------------- /resources/lang/da/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Aktiveret', 6 | 'enabled_instruct' => 'Hvis du deaktiverer dette element, vil det blive udelukket fra rapporter og sitemap, og forhindre at noget bliver vist gennem skabelon-tagget.', 7 | 8 | 'title' => 'Meta Titel', 9 | 'title_instruct' => 'Hver URL på din hjemmeside bør have en unik Meta Titel, ideelt set mindre end 60 tegn lang.', 10 | 11 | 'description' => 'Meta Beskrivelse', 12 | 'description_instruct' => 'Hver URL på din hjemmeside bør have en unik Meta Beskrivelse, ideelt set mindre end 160 tegn lang.', 13 | 14 | 'site_name' => 'Webstedsnavn', 15 | 'site_name_instruct' => 'Deaktiver webstedsnavnet for denne side, hvis det ønskes.', 16 | 17 | 'site_name_position' => 'Webstedsnavn Position', 18 | 'site_name_position_instruct' => 'Justér eventuelt positionen for webstedsnavnet på denne side.', 19 | 20 | 'site_name_separator' => 'Webstedsnavn Separator', 21 | 'site_name_separator_instruct' => 'Justér eventuelt separator for webstedsnavnet på denne side.', 22 | 23 | 'canonical_url' => 'Canonical URL', 24 | 'canonical_url_instruct' => 'Hver URL på din hjemmeside bør have en unik canonical URL.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Vælg indstillinger for robots meta tagget. noindex forhindrer siden i at blive indekseret af søgemaskiner. nofollow forhindrer søgemaskiner i at krybe links.', 28 | 29 | 'image' => 'Socialt billede', 30 | 'image_instruct' => 'Dette billede bruges som forhåndsvisning af sociale netværk.', 31 | 32 | 'twitter_handle' => 'Twitter Handle', 33 | 'twitter_handle_instruct' => 'Overstyr eventuelt Twitter håndtaget for denne side.', 34 | 35 | 'sitemap' => 'Sitemap', 36 | 'sitemap_instruct' => 'Hvis deaktiveret, vil dette element ikke blive vist i sitemap.', 37 | 38 | 'priority' => 'Sitemap: Prioritet', 39 | 'priority_instruct' => 'Prioriteten af denne URL i forhold til andre URLs på dit websted. Gyldige værdier ligger mellem `0,0` og `1,0`.', 40 | 41 | 'change_frequency' => 'Sitemap: Frekvens af ændringer', 42 | 'change_frequency_instruct' => 'Et hint til søgemaskiner om, hvor ofte siden sandsynligvis vil ændre sig.', 43 | 44 | ]; 45 | -------------------------------------------------------------------------------- /resources/lang/da/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Meta Data', 6 | 'meta_section_instruct' => 'Hver URL på din side skal have en unik meta-titel og beskrivelse.', 7 | 8 | 'title' => 'Meta Titel', 9 | 'title_instruct' => 'Vælg et eksisterende felt til at indstille som din **standard** meta-titel. Hver samling og taksonomi kan også have sin egen standard.', 10 | 11 | 'description' => 'Meta Beskrivelse', 12 | 'description_instruct' => 'Vælg et eksisterende felt til at indstille som din **standard** meta-beskrivelse. Hver samling og taksonomi kan også have sin egen standard.', 13 | 14 | 'site_name' => 'Webstedets Navn', 15 | 'site_name_instruct' => 'Det er almindelig praksis at inkludere webstedets navn i meta-titler.', 16 | 17 | 'site_name_position' => 'Webstedets Navn Position', 18 | 'site_name_position_instruct' => 'Før eller efter meta-titlen er op til dig.', 19 | 20 | 'site_name_separator' => 'Webstedets Navn Separator', 21 | 'site_name_separator_instruct' => 'Tegnene mellem titlen og webstedets navn.', 22 | 23 | 'canonical_url' => 'Canonical URL', 24 | 'canonical_url_instruct' => 'Vælg et eksisterende felt til at indstille som din **standard** canonical URL. Hver samling og taksonomi kan også have sin egen standard.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Vælg muligheder for robots meta tag. noindex forhindrer at siden bliver indekseret af søgemaskiner. nofollow forhindrer søgemaskiner i at kravle links.', 28 | 29 | 'image_section' => 'Open Graph', 30 | 'image_section_instruct' => 'Vi genererer automatisk de fleste Open Graph-felter fra dine meta-data og webstedskonfiguration.', 31 | 32 | 'image' => 'Billede', 33 | 'image_instruct' => 'Vælg et standard billedefelt til at repræsentere hver URL, når den deles på sociale netværk.', 34 | 35 | 'social_section' => 'Twitter', 36 | 'social_section_instruct' => 'Vi genererer automatisk de fleste Twitter Card-felter fra dine meta-data og webstedskonfiguration.', 37 | 38 | 'twitter_handle' => 'Twitter Håndtag', 39 | 'twitter_handle_instruct' => 'Vælg et standard Twitter-håndtag, der svarer til webstedet.', 40 | 41 | 'sitemap_section' => 'Websteds Kort', 42 | 'sitemap_section_instruct' => 'Vælg dine standard-sitemap-indstillinger. Hvis du er i tvivl, så lad dem være tomme for de standardstandardværdier.', 43 | 44 | 'priority' => 'Prioritet', 45 | 'priority_instruct' => 'Prioriteten af denne URL i forhold til andre URL’er på dit websted. Gyldige værdier ligger mellem `0,0` og `1,0`.', 46 | 47 | 'change_frequency' => 'Ændringsfrekvens', 48 | 'change_frequency_instruct' => 'Et hint til søgemaskiner om, hvor ofte siden sandsynligvis vil ændre sig.', 49 | 50 | 'search_section' => 'Søgemaskiner', 51 | 'search_section_instruct' => 'At verificere din hjemmeside hos populære søgemaskiner vil hjælpe dig med at spore, hvor godt de kører på din hjemmeside.', 52 | 53 | 'bing_verification' => 'Bing Verificeringskode', 54 | 'bing_verification_instruct' => 'Få din Bing verificeringskode i [Bing Webmaster-værktøjer](https://www.bing.com/toolbox/webmaster).', 55 | 56 | 'google_verification' => 'Google Verificeringskode', 57 | 'google_verification_instruct' => 'Få din Google verificeringskode i [Google Search Console](https://search.google.com/search-console).', 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /resources/lang/da/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Aktiveret', 6 | 'enabled_instruct' => 'Hvis denne sektion deaktiveres, vil den blive ekskluderet fra rapporter og sitemap, og forhindre noget i at blive vist gennem skabelontaggen.', 7 | 8 | 'meta_section' => 'Meta Data', 9 | 10 | 'title' => 'Meta Titel', 11 | 'title_instruct' => 'Vælg et eksisterende felt som denne sektions **standard** meta titel.', 12 | 13 | 'description' => 'Meta Beskrivelse', 14 | 'description_instruct' => 'Vælg et eksisterende felt som denne sektions **standard** meta beskrivelse.', 15 | 16 | 'site_name' => 'Webstedsnavn', 17 | 'site_name_instruct' => 'Deaktiver eventuelt webstedsnavnet for denne sektion.', 18 | 19 | 'site_name_position' => 'Webstedsnavn position', 20 | 'site_name_position_instruct' => 'Justér eventuelt positionen for webstedsnavnet i denne sektion.', 21 | 22 | 'site_name_separator' => 'Webstedsnavn separator', 23 | 'site_name_separator_instruct' => 'Justér eventuelt separationskarakteren for webstedsnavnet i denne sektion.', 24 | 25 | 'canonical_url' => 'Canonical URL', 26 | 'canonical_url_instruct' => 'Vælg et eksisterende felt som denne sektions **standard** canonical URL.', 27 | 28 | 'robots' => 'Robots', 29 | 'robots_instruct' => 'Vælg indstillinger for robots meta-tagget. noindex forhindrer, at siden indekseres af søgemaskiner. nofollow forhindrer, at søgemaskinerne crawler links.', 30 | 31 | 'og_section' => 'Open Graph', 32 | 'og_section_instruct' => 'Vi genererer automatisk de fleste Open Graph-felter fra din meta data og websteds konfiguration.', 33 | 34 | 'image' => 'Billede', 35 | 'image_instruct' => 'Vælg et standardbilledefelt til at repræsentere hver URL i denne sektion, når det deles på sociale netværk.', 36 | 37 | 'twitter_handle' => 'Twitter brugernavn', 38 | 'twitter_handle_instruct' => 'Vælg et standard Twitter-brugernavn, der svarer til denne sektion.', 39 | 40 | 'sitemap_section' => 'Sitemap', 41 | 42 | 'sitemap' => 'Sitemap', 43 | 'sitemap_instruct' => 'Hvis deaktiveret, vil emner i denne sektion ikke blive vist i sitemap.', 44 | 45 | 'show_future' => 'Vis fremtidige indlæg', 46 | 'show_future_instruct' => 'Hvis deaktiveret, vil indlæg, der er dateret i fremtiden, ikke blive vist i sitemap.', 47 | 48 | 'show_past' => 'Vis tidligere indlæg', 49 | 'show_past_instruct' => 'Hvis deaktiveret, vil indlæg, der er dateret i fortiden, ikke blive vist i sitemap.', 50 | 51 | 'priority' => 'Prioritet', 52 | 'priority_instruct' => 'Prioriteten af disse URLs i forhold til andre URLs på dit websted. Gyldige værdier spænder fra `0,0` til `1,0`.', 53 | 54 | 'change_frequency' => 'Ændringsfrekvens', 55 | 'change_frequency_instruct' => 'En antydning til søgemaskiner om, hvor ofte siderne i denne sektion sandsynligvis vil ændre sig.', 56 | 57 | ]; 58 | -------------------------------------------------------------------------------- /resources/lang/da/settings.php: -------------------------------------------------------------------------------- 1 | 'Arkivbeholderen der bruges til alle SEO Pro’s billedefelter.', 6 | 7 | 'og_image_dimensions' => 'OpenGraph Billedstørrelse', 8 | 'og_image_dimensions_instruct' => 'Ifølge denne artikel er den ideelle billedstørrelse til Facebook og Reddit Open Graph-tags 1200x1200 pixels.', 9 | 10 | 'open_graph_image_width' => 'Bredde', 11 | 'open_graph_image_width_instruct' => 'I pixels', 12 | 13 | 'open_graph_image_height' => 'Højde', 14 | 'open_graph_image_height_instruct' => 'I pixels', 15 | 16 | 'sitemap_enabled' => 'Aktiveret', 17 | 'sitemap_enabled_instruct' => 'Hvis aktiveret, vil en sitemap xml-fil kunne ses på URL’en, der er defineret nedenfor.', 18 | 19 | 'sitemap_url' => 'Sitemap URL', 20 | 'sitemap_url_instruct' => 'Placeringen af sitemap i forhold til roden af dit standard sprogs forside.', 21 | 22 | 'sitemap_cache_length' => 'Cache længde', 23 | 'sitemap_cache_length_instruct' => 'Hvor lang tid sitemap skal cachet, i minutter.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/de/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Aktiviert', 6 | 'enabled_instruct' => 'Ist dieser Eintrag deaktiviert, wird er von Berichten und der Sitemap ausgeschlossen und es wird nichts durch das Template-Tag gerendert.', 7 | 8 | 'title' => 'Meta-Titel', 9 | 'title_instruct' => 'Jede URL deiner Website sollte einen eindeutigen Meta-Titel haben, der idealerweise weniger als 60 Zeichen lang ist.', 10 | 11 | 'description' => 'Meta-Beschreibung', 12 | 'description_instruct' => 'Jede URL deiner Website sollte eine eindeutige Meta-Beschreibung haben, die idealerweise weniger als 160 Zeichen lang ist.', 13 | 14 | 'site_name' => 'Name der Website', 15 | 'site_name_instruct' => 'Optional den Namen der Website für diese Seite deaktivieren.', 16 | 17 | 'site_name_position' => 'Name der Website: Position', 18 | 'site_name_position_instruct' => 'Optional die Position für diese Seite anpassen.', 19 | 20 | 'site_name_separator' => 'Name der Website: Trennzeichen', 21 | 'site_name_separator_instruct' => 'Optional das Trennzeichen zwischen Meta-Titel und dem Namen der Website für diese Seite anpassen.', 22 | 23 | 'canonical_url' => 'Kanonische URL', 24 | 'canonical_url_instruct' => 'Jede URL auf deiner Website sollte eine eindeutige kanonische URL haben.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Wähle Optionen für das Robots Meta-Tag. `noindex` verhindert, dass die Seite von Suchmaschinen indiziert wird. `nofollow` verhindert, dass Suchmaschinen Links crawlen.', 28 | 29 | 'image' => 'Social Media Bild', 30 | 'image_instruct' => 'Dieses Bild wird als Vorschaubild für soziale Netzwerke verwendet.', 31 | 32 | 'twitter_handle' => 'Twitter-Handle', 33 | 'twitter_handle_instruct' => 'Optional den Twitter-Handle für diese Seite überschreiben.', 34 | 35 | 'sitemap' => 'Sitemap', 36 | 'sitemap_instruct' => 'Ist diese Option deaktiviert, wird dieser Eintrag nicht in der Sitemap angezeigt.', 37 | 38 | 'priority' => 'Sitemap: Priorität', 39 | 'priority_instruct' => 'Die Wichtigkeit dieser URL relativ zu anderen URLs auf deiner Website. Gültige Werte reichen von `0.0` bis `1.0`.', 40 | 41 | 'change_frequency' => 'Sitemap: Frequenz', 42 | 'change_frequency_instruct' => 'Ein Hinweis für Suchmaschinen, wie häufig sich die Seite wahrscheinlich ändern wird.', 43 | 44 | ]; 45 | -------------------------------------------------------------------------------- /resources/lang/de/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Metadaten ', 6 | 'meta_section_instruct' => 'Jede URL deiner Website sollte einen Meta-Titel und eine Meta-Beschreibung haben, die eindeutig sind.', 7 | 8 | 'title' => 'Meta-Titel', 9 | 'title_instruct' => 'Wähle für den Meta-Titel ein vorhandenes Feld als Standard. Jede Sammlung und Taxonomie kann auch ihre eigene Einstellung haben.', 10 | 11 | 'description' => 'Meta-Beschreibung', 12 | 'description_instruct' => 'Wähle für die Meta-Beschreibung ein vorhandenes Feld als Standard. Jede Sammlung und Taxonomie kann auch ihre eigene Einstellung haben.', 13 | 14 | 'site_name' => 'Name der Website', 15 | 'site_name_instruct' => 'Es ist üblich, den Namen der Website in die Seitentitel einzufügen.', 16 | 17 | 'site_name_position' => 'Name der Website: Position', 18 | 'site_name_position_instruct' => 'Ob vor oder nach dem Titel bleibt dir überlassen.', 19 | 20 | 'site_name_separator' => 'Name der Website: Trennzeichen', 21 | 'site_name_separator_instruct' => 'Das (oder die) Zeichen zwischen Titel und Name der Website.', 22 | 23 | 'canonical_url' => 'Kanonische URL', 24 | 'canonical_url_instruct' => 'Wähle für die kanonische URL ein vorhandenes Feld als Standard. Jede Sammlung und Taxonomie kann auch ihre eigene Einstellung haben.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Wähle Optionen für das Robots Meta-Tag. `noindex` verhindert, dass die Seite von Suchmaschinen indiziert wird. `nofollow` verhindert, dass Suchmaschinen Links crawlen.', 28 | 29 | 'image_section' => 'Open Graph', 30 | 'image_section_instruct' => 'Wir erstellen die meisten Open-Graph Felder automatisch aus deinen Metadaten und der Website-Konfiguration.', 31 | 32 | 'image' => 'Bild', 33 | 'image_instruct' => 'Wähle ein Feld für ein Bild, das jede URL beim Teilen in sozialen Netzwerken als Standard anzeigen soll.', 34 | 35 | 'social_section' => 'Twitter', 36 | 'social_section_instruct' => 'Wir erstellen die meisten Twitter-Card Felder automatisch aus deinen Metadaten und der Website-Konfiguration.', 37 | 38 | 'twitter_handle' => 'Twitter-Handle', 39 | 'twitter_handle_instruct' => 'Wähle einen voreingestellten Twitter-Handle, der zur Website passt.', 40 | 41 | 'sitemap_section' => 'Sitemap', 42 | 'sitemap_section_instruct' => 'Wähle deine Voreinstellungen für die Sitemap. Wenn du unsicher sind, lasse die Felder zugunsten der üblichen Standardwerte leer.', 43 | 44 | 'priority' => 'Priorität', 45 | 'priority_instruct' => 'Die Wichtigkeit dieser URL relativ zu anderen URLs auf deiner Website. Gültige Werte reichen von `0.0` bis `1.0`.', 46 | 47 | 'change_frequency' => 'Frequenz', 48 | 'change_frequency_instruct' => 'Ein Hinweis für Suchmaschinen, wie häufig sich die Seite wahrscheinlich ändern wird.', 49 | 50 | 'search_section' => 'Suchmaschinen', 51 | 'search_section_instruct' => 'Durch die Verifizierung deiner Website bei beliebten Suchmaschinen kannst du prüfen, wie gut deine Website von diesen gecrawlt wird.', 52 | 53 | 'bing_verification' => 'Bing Verifizierungscode', 54 | 'bing_verification_instruct' => 'Hol dir deinen Bing-Verifizierungscode in den [Bing Webmaster Tools](https://www.bing.com/toolbox/webmaster).', 55 | 56 | 'google_verification' => 'Google Verifizierungscode', 57 | 'google_verification_instruct' => 'Hol dir deinen Googler-Verifizierungscode in der [Google Search Console](https://search.google.com/search-console).', 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /resources/lang/de/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Aktiviert', 6 | 'enabled_instruct' => 'Ist dieser Bereich deaktiviert, wird er von Berichten und der Sitemap ausgeschlossen und es wird nichts durch das Template-Tag gerendert.', 7 | 8 | 'meta_section' => 'Metadaten', 9 | 10 | 'title' => 'Meta-Titel', 11 | 'title_instruct' => 'Wähle für die Meta-Titel in diesem Bereich ein vorhandenes Feld als Standard.', 12 | 13 | 'description' => 'Meta-Beschreibung', 14 | 'description_instruct' => 'Wähle für die Meta-Beschreibungen in diesem Bereich ein vorhandenes Feld als Standard.', 15 | 16 | 'site_name' => 'Name der Website', 17 | 'site_name_instruct' => 'Optional den Namen der Website in diesem Bereich deaktivieren.', 18 | 19 | 'site_name_position' => 'Name der Website: Position', 20 | 'site_name_position_instruct' => 'Optional die Position in diesem Bereich anpassen.', 21 | 22 | 'site_name_separator' => 'Name der Website: Trennzeichen', 23 | 'site_name_separator_instruct' => 'Optional das Trennzeichen zwischen Meta-Titel und dem Namen der Website in diesem Bereich anpassen.', 24 | 25 | 'canonical_url' => 'Kanonische URL', 26 | 'canonical_url_instruct' => 'Wähle für die kanonischen URLs in diesem Bereich ein vorhandenes Feld als Standard.', 27 | 28 | 'robots' => 'Robots', 29 | 'robots_instruct' => 'Wähle Optionen für das Robots Meta-Tag. `noindex` verhindert, dass die Seite von Suchmaschinen indiziert wird. `nofollow` verhindert, dass Suchmaschinen Links crawlen.', 30 | 31 | 'og_section' => 'Open Graph', 32 | 'og_section_instruct' => 'Wir erstellen die meisten Open-Graph Felder automatisch aus deinen Metadaten und der Website-Konfiguration.', 33 | 34 | 'image' => 'Bild', 35 | 'image_instruct' => 'Wähle ein Feld für ein Bild, das jede URL in diesem Bereich beim Teilen in sozialen Netzwerken als Standard anzeigen soll.', 36 | 37 | 'twitter_handle' => 'Twitter-Handle', 38 | 'twitter_handle_instruct' => 'Wähle einen für diesen Bereich passenden Twitter-Handle als Standard.', 39 | 40 | 'sitemap_section' => 'Sitemap', 41 | 42 | 'sitemap' => 'Sitemap', 43 | 'sitemap_instruct' => 'Ist diese Option deaktiviert, werden Einträge in diesem Bereich nicht in der Sitemap angezeigt.', 44 | 45 | 'show_future' => 'Zeige Einträge in der Zukunft', 46 | 'show_future_instruct' => 'Ist diese Option deaktiviert, werden in der Zukunft liegende Einträge nicht in der Sitemap angezeigt.', 47 | 48 | 'show_past' => 'Zeige Einträge in der Vergangenheit', 49 | 'show_past_instruct' => 'Ist diese Option deaktiviert, werden in der Vergangenheit liegende Einträge nicht in der Sitemap angezeigt.', 50 | 51 | 'priority' => 'Sitemap: Priorität', 52 | 'priority_instruct' => 'Die Wichtigkeit dieser URLs relativ zu anderen URLs auf deiner Website. Gültige Werte reichen von `0.0` bis `1.0`.', 53 | 54 | 'change_frequency' => 'Sitemap: Frequenz', 55 | 'change_frequency_instruct' => 'Ein Hinweis für Suchmaschinen, wie häufig sich die Seiten in diesem Bereich wahrscheinlich ändern werden.', 56 | 57 | ]; 58 | -------------------------------------------------------------------------------- /resources/lang/de/settings.php: -------------------------------------------------------------------------------- 1 | 'Der Asset-Container für alle Bildfelder von SEO Pro.', 6 | 7 | 'og_image_dimensions' => 'OpenGraph Bildabmessungen', 8 | 'og_image_dimensions_instruct' => 'Laut diesem Artikel ist die ideale Bildgröße für Facebook und Reddit Open Graph Tags 1200×1200 Pixel.', 9 | 10 | 'open_graph_image_width' => 'Breite', 11 | 'open_graph_image_width_instruct' => 'In Pixel', 12 | 13 | 'open_graph_image_height' => 'Höhe', 14 | 'open_graph_image_height_instruct' => 'In Pixel', 15 | 16 | 'sitemap_enabled' => 'Aktiviert', 17 | 'sitemap_enabled_instruct' => 'Ist diese Option aktiviert, kann eine Sitemap-xml-Datei unter der unten festgelegten URL angezeigt werden.', 18 | 19 | 'sitemap_url' => 'Sitemap URL', 20 | 'sitemap_url_instruct' => 'Die Position der Sitemap relativ zum Stammverzeichnis der Startseite deiner Standard-Lokale.', 21 | 22 | 'sitemap_cache_length' => 'Cache Länge', 23 | 'sitemap_cache_length_instruct' => 'Wie lange die Sitemap zwischengespeichert werden soll, in Minuten.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/de_CH/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Aktiviert', 6 | 'enabled_instruct' => 'Ist dieser Eintrag deaktiviert, wird er von Berichten und der Sitemap ausgeschlossen und es wird nichts durch das Template-Tag gerendert.', 7 | 8 | 'title' => 'Meta-Titel', 9 | 'title_instruct' => 'Jede URL deiner Website sollte einen eindeutigen Meta-Titel haben, der idealerweise weniger als 60 Zeichen lang ist.', 10 | 11 | 'description' => 'Meta-Beschreibung', 12 | 'description_instruct' => 'Jede URL deiner Website sollte eine eindeutige Meta-Beschreibung haben, die idealerweise weniger als 160 Zeichen lang ist.', 13 | 14 | 'site_name' => 'Name der Website', 15 | 'site_name_instruct' => 'Optional den Namen der Website für diese Seite deaktivieren.', 16 | 17 | 'site_name_position' => 'Name der Website: Position', 18 | 'site_name_position_instruct' => 'Optional die Position für diese Seite anpassen.', 19 | 20 | 'site_name_separator' => 'Name der Website: Trennzeichen', 21 | 'site_name_separator_instruct' => 'Optional das Trennzeichen zwischen Meta-Titel und dem Namen der Website für diese Seite anpassen.', 22 | 23 | 'canonical_url' => 'Kanonische URL', 24 | 'canonical_url_instruct' => 'Jede URL auf deiner Website sollte eine eindeutige kanonische URL haben.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Wähle Optionen für das Robots Meta-Tag. `noindex` verhindert, dass die Seite von Suchmaschinen indexiert wird. `nofollow` verhindert, dass Suchmaschinen Links crawlen.', 28 | 29 | 'image' => 'Social Media Bild', 30 | 'image_instruct' => 'Dieses Bild wird als Vorschaubild für soziale Netzwerke verwendet.', 31 | 32 | 'twitter_handle' => 'Twitter-Handle', 33 | 'twitter_handle_instruct' => 'Optional den Twitter-Handle für diese Seite überschreiben.', 34 | 35 | 'sitemap' => 'Sitemap', 36 | 'sitemap_instruct' => 'Ist diese Option deaktiviert, wird dieser Eintrag nicht in der Sitemap angezeigt.', 37 | 38 | 'priority' => 'Sitemap: Priorität', 39 | 'priority_instruct' => 'Die Wichtigkeit dieser URL relativ zu anderen URLs auf deiner Website. Gültige Werte reichen von `0.0` bis `1.0`.', 40 | 41 | 'change_frequency' => 'Sitemap: Frequenz', 42 | 'change_frequency_instruct' => 'Ein Hinweis für Suchmaschinen, wie häufig sich die Seite wahrscheinlich ändern wird.', 43 | 44 | ]; 45 | -------------------------------------------------------------------------------- /resources/lang/de_CH/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Aktiviert', 6 | 'enabled_instruct' => 'Ist dieser Bereich deaktiviert, wird er von Berichten und der Sitemap ausgeschlossen und es wird nichts durch das Template-Tag gerendert.', 7 | 8 | 'meta_section' => 'Metadaten', 9 | 10 | 'title' => 'Meta-Titel', 11 | 'title_instruct' => 'Wähle für die Meta-Titel in diesem Bereich ein vorhandenes Feld als Standard.', 12 | 13 | 'description' => 'Meta-Beschreibung', 14 | 'description_instruct' => 'Wähle für die Meta-Beschreibungen in diesem Bereich ein vorhandenes Feld als Standard.', 15 | 16 | 'site_name' => 'Name der Website', 17 | 'site_name_instruct' => 'Optional den Namen der Website in diesem Bereich deaktivieren.', 18 | 19 | 'site_name_position' => 'Name der Website: Position', 20 | 'site_name_position_instruct' => 'Optional die Position in diesem Bereich anpassen.', 21 | 22 | 'site_name_separator' => 'Name der Website: Trennzeichen', 23 | 'site_name_separator_instruct' => 'Optional das Trennzeichen zwischen Meta-Titel und dem Namen der Website in diesem Bereich anpassen.', 24 | 25 | 'canonical_url' => 'Kanonische URL', 26 | 'canonical_url_instruct' => 'Wähle für die kanonischen URLs in diesem Bereich ein vorhandenes Feld als Standard.', 27 | 28 | 'robots' => 'Robots', 29 | 'robots_instruct' => 'Wähle Optionen für das Robots Meta-Tag. `noindex` verhindert, dass die Seite von Suchmaschinen indexiert wird. `nofollow` verhindert, dass Suchmaschinen Links crawlen.', 30 | 31 | 'og_section' => 'Open Graph', 32 | 'og_section_instruct' => 'Wir erstellen die meisten Open-Graph Felder automatisch aus deinen Metadaten und der Website-Konfiguration.', 33 | 34 | 'image' => 'Bild', 35 | 'image_instruct' => 'Wähle ein Feld für ein Bild, das jede URL in diesem Bereich beim Teilen in sozialen Netzwerken als Standard anzeigen soll.', 36 | 37 | 'twitter_handle' => 'Twitter-Handle', 38 | 'twitter_handle_instruct' => 'Wähle einen für diesen Bereich passenden Twitter-Handle als Standard.', 39 | 40 | 'sitemap_section' => 'Sitemap', 41 | 42 | 'sitemap' => 'Sitemap', 43 | 'sitemap_instruct' => 'Ist diese Option deaktiviert, werden Einträge in diesem Bereich nicht in der Sitemap angezeigt.', 44 | 45 | 'show_future' => 'Zeige Einträge in der Zukunft', 46 | 'show_future_instruct' => 'Ist diese Option deaktiviert, werden in der Zukunft liegende Einträge nicht in der Sitemap angezeigt.', 47 | 48 | 'show_past' => 'Zeige Einträge in der Vergangenheit', 49 | 'show_past_instruct' => 'Ist diese Option deaktiviert, werden in der Vergangenheit liegende Einträge nicht in der Sitemap angezeigt.', 50 | 51 | 'priority' => 'Sitemap: Priorität', 52 | 'priority_instruct' => 'Die Wichtigkeit dieser URLs relativ zu anderen URLs auf deiner Website. Gültige Werte reichen von `0.0` bis `1.0`.', 53 | 54 | 'change_frequency' => 'Sitemap: Frequenz', 55 | 'change_frequency_instruct' => 'Ein Hinweis für Suchmaschinen, wie häufig sich die Seiten in diesem Bereich wahrscheinlich ändern werden.', 56 | 57 | ]; 58 | -------------------------------------------------------------------------------- /resources/lang/de_CH/settings.php: -------------------------------------------------------------------------------- 1 | 'Der Asset-Container für alle Bildfelder von SEO Pro.', 6 | 7 | 'og_image_dimensions' => 'OpenGraph Bildabmessungen', 8 | 'og_image_dimensions_instruct' => 'Laut diesem Artikel ist die ideale Bildgrösse für Facebook und Reddit Open Graph Tags 1200×1200 Pixel.', 9 | 10 | 'open_graph_image_width' => 'Breite', 11 | 'open_graph_image_width_instruct' => 'In Pixel', 12 | 13 | 'open_graph_image_height' => 'Höhe', 14 | 'open_graph_image_height_instruct' => 'In Pixel', 15 | 16 | 'sitemap_enabled' => 'Aktiviert', 17 | 'sitemap_enabled_instruct' => 'Ist diese Option aktiviert, kann eine Sitemap-xml-Datei unter der unten festgelegten URL angezeigt werden.', 18 | 19 | 'sitemap_url' => 'Sitemap URL', 20 | 'sitemap_url_instruct' => 'Die Position der Sitemap relativ zum Stammverzeichnis der Startseite deiner Standard-Lokale.', 21 | 22 | 'sitemap_cache_length' => 'Cache Länge', 23 | 'sitemap_cache_length_instruct' => 'Wie lange die Sitemap zwischengespeichert werden soll, in Minuten.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/en/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Enabled', 6 | 'enabled_instruct' => 'Disabling this item will exclude it from reports and the sitemap, and prevent anything from being rendered through the template tag.', 7 | 8 | 'title' => 'Meta Title', 9 | 'title_instruct' => 'Every URL in your site should have a unique Meta Title, ideally less than 60 characters long.', 10 | 11 | 'description' => 'Meta Description', 12 | 'description_instruct' => 'Every URL in your site should have a unique Meta Description, ideally less than 160 characters long.', 13 | 14 | 'site_name' => 'Site Name', 15 | 'site_name_instruct' => 'Optionally disable the site name for this page.', 16 | 17 | 'site_name_position' => 'Site Name Position', 18 | 'site_name_position_instruct' => 'Optionally adjust the position for this page.', 19 | 20 | 'site_name_separator' => 'Site Name Separator', 21 | 'site_name_separator_instruct' => 'Optionally adjust the separator for this page.', 22 | 23 | 'canonical_url' => 'Canonical URL', 24 | 'canonical_url_instruct' => 'Every URL in your site should have a unique canonical URL.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Pick options for the robots meta tag. noindex prevents the page being indexed by search engines. nofollow prevents search engines from crawling links.', 28 | 29 | 'image' => 'Social Image', 30 | 'image_instruct' => 'This image is used as a social network preview image.', 31 | 32 | 'twitter_handle' => 'Twitter Handle', 33 | 'twitter_handle_instruct' => 'Optionally override the twitter handle for this page.', 34 | 35 | 'sitemap' => 'Sitemap', 36 | 'sitemap_instruct' => 'If disabled, this item will not appear in the sitemap.', 37 | 38 | 'priority' => 'Sitemap: Priority', 39 | 'priority_instruct' => 'The priority of this URL relative to other URLs on your site. Valid values range from `0.0` to `1.0`.', 40 | 41 | 'change_frequency' => 'Sitemap: Change Frequency', 42 | 'change_frequency_instruct' => 'A hint to search engines on how frequently the page is likely to change.', 43 | 44 | ]; 45 | -------------------------------------------------------------------------------- /resources/lang/en/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Meta Data', 6 | 'meta_section_instruct' => 'Every URL in your site should have a unique meta title and description.', 7 | 8 | 'title' => 'Meta Title', 9 | 'title_instruct' => 'Pick an existing field to set as your **default** meta title. Each Collection and Taxonomy can also have its own default.', 10 | 11 | 'description' => 'Meta Description', 12 | 'description_instruct' => 'Pick an existing field to set as your **default** meta description. Each Collection and Taxonomy can also have its own default.', 13 | 14 | 'site_name' => 'Site Name', 15 | 'site_name_instruct' => "It's common practice to include the site's name in meta titles.", 16 | 17 | 'site_name_position' => 'Site Name Position', 18 | 'site_name_position_instruct' => 'Before or after the the meta title is up to you.', 19 | 20 | 'site_name_separator' => 'Site Name Separator', 21 | 'site_name_separator_instruct' => 'The character(s) between the title and site name.', 22 | 23 | 'canonical_url' => 'Canonical URL', 24 | 'canonical_url_instruct' => 'Pick an existing field to set as your **default** canonical URL. Each Collection and Taxonomy can also have its own default.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Pick options for the robots meta tag. noindex prevents the page being indexed by search engines. nofollow prevents search engines from crawling links.', 28 | 29 | 'image_section' => 'Open Graph', 30 | 'image_section_instruct' => 'We automatically generate most Open Graph fields from your meta data and site configuration.', 31 | 32 | 'image' => 'Image', 33 | 'image_instruct' => 'Choose a default image field to represent each URL when shared on social networks.', 34 | 35 | 'social_section' => 'Twitter', 36 | 'social_section_instruct' => 'We automatically generate most Twitter Card fields from your meta data and site configuration.', 37 | 38 | 'twitter_handle' => 'Twitter Handle', 39 | 'twitter_handle_instruct' => 'Choose a default twitter handle that corresponds to the site.', 40 | 41 | 'sitemap_section' => 'Site Map', 42 | 'sitemap_section_instruct' => "Choose your default sitemap settings. If you're not sure, leave them blank for the standard default values.", 43 | 44 | 'priority' => 'Priority', 45 | 'priority_instruct' => 'The priority of this URL relative to other URLs on your site. Valid values range from `0.0` to `1.0`.', 46 | 47 | 'change_frequency' => 'Change Frequency', 48 | 'change_frequency_instruct' => 'A hint to search engines on how frequently the page is likely to change.', 49 | 50 | 'search_section' => 'Search Engines', 51 | 'search_section_instruct' => "Verifying your site with popular search engines will help you track how well they're crawling your site.", 52 | 53 | 'bing_verification' => 'Bing Verification Code', 54 | 'bing_verification_instruct' => 'Get your Bing verification code in [Bing Webmaster Tools](https://www.bing.com/toolbox/webmaster).', 55 | 56 | 'google_verification' => 'Google Verification Code', 57 | 'google_verification_instruct' => 'Get your Google verification code in [Google Search Console](https://search.google.com/search-console).', 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /resources/lang/en/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Enabled', 6 | 'enabled_instruct' => 'Disabling this section will exclude it from reports and the sitemap, and prevent anything from being rendered through the template tag.', 7 | 8 | 'meta_section' => 'Meta Data', 9 | 10 | 'title' => 'Meta Title', 11 | 'title_instruct' => "Pick an existing field to set as this section's **default** meta title.", 12 | 13 | 'description' => 'Meta Description', 14 | 'description_instruct' => "Pick an existing field to set as this section's **default** meta description.", 15 | 16 | 'site_name' => 'Site Name', 17 | 'site_name_instruct' => 'Optionally disable the site name for this section.', 18 | 19 | 'site_name_position' => 'Site Name Position', 20 | 'site_name_position_instruct' => 'Optionally adjust the position for this section.', 21 | 22 | 'site_name_separator' => 'Site Name Separator', 23 | 'site_name_separator_instruct' => 'Optionally adjust the separator for this section.', 24 | 25 | 'canonical_url' => 'Canonical URL', 26 | 'canonical_url_instruct' => "Pick an existing field to set as this section's **default** canonical URL.", 27 | 28 | 'robots' => 'Robots', 29 | 'robots_instruct' => 'Pick options for the robots meta tag. noindex prevents the page being indexed by search engines. nofollow prevents search engines from crawling links.', 30 | 31 | 'og_section' => 'Open Graph', 32 | 'og_section_instruct' => 'We automatically generate most Open Graph fields from your meta data and site configuration.', 33 | 34 | 'image' => 'Image', 35 | 'image_instruct' => 'Choose a default image field to represent each URL in this section when shared on social networks.', 36 | 37 | 'twitter_handle' => 'Twitter Handle', 38 | 'twitter_handle_instruct' => 'Choose a default twitter handle that corresponds to this section.', 39 | 40 | 'sitemap_section' => 'Site Map', 41 | 42 | 'sitemap' => 'Sitemap', 43 | 'sitemap_instruct' => 'If disabled, items in this section will not appear in the sitemap.', 44 | 45 | 'show_future' => 'Show Future Entries', 46 | 'show_future_instruct' => 'If disabled, entries dated in the future will not appear in the sitemap.', 47 | 48 | 'show_past' => 'Show Past Entries', 49 | 'show_past_instruct' => 'If disabled, entries dated in the past will not appear in the sitemap.', 50 | 51 | 'priority' => 'Priority', 52 | 'priority_instruct' => 'The priority of these URLs relative to other URLs on your site. Valid values range from `0.0` to `1.0`.', 53 | 54 | 'change_frequency' => 'Change Frequency', 55 | 'change_frequency_instruct' => 'A hint to search engines on how frequently the pages in this section are likely to change.', 56 | 57 | ]; 58 | -------------------------------------------------------------------------------- /resources/lang/en/settings.php: -------------------------------------------------------------------------------- 1 | "The asset container used for any of SEO Pro's image fields.", 6 | 7 | 'og_image_dimensions' => 'OpenGraph Image Dimensions', 8 | 'og_image_dimensions_instruct' => 'According this this article, the ideal image size for Facebook and Reddit Open Graph tags is 1200x1200 pixels.', 9 | 10 | 'open_graph_image_width' => 'Width', 11 | 'open_graph_image_width_instruct' => 'In pixels', 12 | 13 | 'open_graph_image_height' => 'Height', 14 | 'open_graph_image_height_instruct' => 'In pixels', 15 | 16 | 'sitemap_enabled' => 'Enabled', 17 | 'sitemap_enabled_instruct' => 'If enabled, a sitemap xml file will be viewable at the URL defined below.', 18 | 19 | 'sitemap_url' => 'Sitemap URL', 20 | 'sitemap_url_instruct' => "The location of the sitemap relative to the root of your default locale's home page.", 21 | 22 | 'sitemap_cache_length' => 'Cache Length', 23 | 'sitemap_cache_length_instruct' => 'How long the sitemap should get cached, in minutes.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/es/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Habilitado', 6 | 'enabled_instruct' => 'Desabilitando este elemento lo excluirá de los reportes y del sitemap, además la etiqueta no renderizará ningún contenido.', 7 | 8 | 'title' => 'Meta Título', 9 | 'title_instruct' => 'Cada URL en tu sitio debería llevar un Meta Título único, idealmente de menos de 60 caracteres.', 10 | 11 | 'description' => 'Meta Descripción', 12 | 'description_instruct' => 'Cada URL en tu sitio debería llevar un Meta Descripción único, idealmente de menos de 160 caracteres.', 13 | 14 | 'image' => 'Imagen Social', 15 | 'image_instruct' => 'Esta imagen será usada como previsualización para redes sociales.', 16 | 17 | 'sitemap' => 'Sitemap', 18 | 'sitemap_instruct' => 'Deshabilitando este campo, este elemento no aparecerá en el sitemap.', 19 | 20 | 'priority' => 'Sitemap: Prioridad', 21 | 'priority_instruct' => 'La prioridad de esta URL relativa a otras URLs en tu sitio. Los valores válidos van de `0.0` a `1.0`.', 22 | 23 | 'change_frequency' => 'Sitemap: Frecuencia de cambio', 24 | 'change_frequency_instruct' => 'Una pista para los motores de búsqueda sobre la frecuencia de que esta página es posible que cambie.', 25 | 26 | ]; 27 | -------------------------------------------------------------------------------- /resources/lang/es/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Metadatos', 6 | 'meta_section_instruct' => 'Cada URL en tu sitio debería tener un Meta Título y Descripción únicos.', 7 | 8 | 'title' => 'Meta Título', 9 | 'title_instruct' => 'Seleciona un campo existente para que sea tu meta título **por defecto**. Cada Colección y Taxonomía puede tener su propio campo por defecto.', 10 | 11 | 'site_name' => 'Nombre del Sitio', 12 | 'site_name_instruct' => 'Es una práctica común incluír el nombre del sitio en los meta títulos.', 13 | 14 | 'site_name_position' => 'Posición del Nombre del Sitio', 15 | 'site_name_position_instruct' => 'Antes o después del meta título, tu mismo.', 16 | 17 | 'site_name_separator' => 'Separador del Nombre del Sitio', 18 | 'site_name_separator_instruct' => 'El caracter o caracteres entre el meta título y el nombre del sitio.', 19 | 20 | 'description' => 'Meta Descripción', 21 | 'description_instruct' => 'Seleciona un campo existente para que sea tu meta descripción **por defecto**. Cada Colección y Taxonomía puede tener su propio campo por defecto.', 22 | 23 | 'image_section' => 'Open Graph', 24 | 'image_section_instruct' => 'Generamos de forma automática la mayoría de campos Open Graph a partir de tus metadatos y configuración del sitio.', 25 | 26 | 'image' => 'Imágen', 27 | 'image_instruct' => 'Selecciona un campo de imágen por defecto que represente cada URL cuando sea compartida en las redes sociales.', 28 | 29 | 'social_section' => 'Twitter', 30 | 'social_section_instruct' => 'Generamos de forma automatica la mayoría de campos para la tarjeta de Twitter de tus metadatos y confitguración del sitio.', 31 | 32 | 'twitter_handle' => 'Usuario de Twitter', 33 | 'twitter_handle_instruct' => '_(Opcional)_ Establece el nombre de usuario de twitter que está asociado a este sitio.', 34 | 35 | 'sitemap_section' => 'Site Map', 36 | 'sitemap_section_instruct' => 'Selecciona tu configuración del sitemap por defecto. Si no estás seguro, déjalos en blaco para que se usen los valores por defecto.', 37 | 38 | 'priority' => 'Prioridad', 39 | 'priority_instruct' => 'La prioridad de esta URL relativa a otras URLs en tu sitio. Los valores válidos están entre `0.0` y `1.0`.', 40 | 41 | 'change_frequency' => 'Sitemap: Frecuencia de cambio', 42 | 'change_frequency_instruct' => 'Una pista para los motores de búsqueda sobre la frecuencia de que esta página es posible que cambie.', 43 | 44 | ]; 45 | -------------------------------------------------------------------------------- /resources/lang/es/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Habilitado', 6 | 'enabled_instruct' => 'Deshabilitando esta sección la excluirá de reportes y del sitemap, y nada será renderizado a través de la etiqueta.', 7 | 8 | 'meta_section' => 'Metadatos', 9 | 10 | 'title' => 'Meta Título', 11 | 'title_instruct' => 'Seleciona un campo existente para que ejerza como el meta título **por defecto** de esta sección.', 12 | 13 | 'description' => 'Meta Descripción', 14 | 'description_instruct' => 'Seleciona un campo existente para que ejerza como la meta descripción **por defecto** de esta sección.', 15 | 16 | 'og_section' => 'Open Graph', 17 | 'og_section_instruct' => 'Generamos de forma automática la mayoría de campos Open Graph a partir de tus metadatos y configuración del sitio.', 18 | 19 | 'image' => 'Imágen', 20 | 'image_instruct' => 'Selecciona un campo de imágen por defecto que represente cada URL cuando sea compartida en las redes sociales.', 21 | 22 | 'sitemap_section' => 'SiteMap', 23 | 24 | 'sitemap' => 'Habilitado', 25 | 'sitemap_instruct' => 'Si está deshabilitado, esta sección no aparecerá en el sitemap..', 26 | 27 | 'show_future' => 'Mostrar entradas futuras', 28 | 'show_future_instruct' => 'Si está deshabilitado, las entradas que tengan una fecha en el futuro no aparecerán en el sitemap.', 29 | 30 | 'show_past' => 'Mostrar entradas pasadas', 31 | 'show_past_instruct' => 'Si está deshabilitado, las entradas que tengan una fecha en el pasado no aparecerán en el sitemap.', 32 | 33 | 'priority' => 'Prioridad', 34 | 'priority_instruct' => 'La prioridad de estas URLs relativas a otras URLs en tu sitio. Los valores válidos están entre `0.0` y `1.0`.', 35 | 36 | 'change_frequency' => 'Sitemap: Frecuencia de cambio', 37 | 'change_frequency_instruct' => 'Una pista para los motores de búsqueda sobre la frecuencia de que esta sección es posible que cambie.', 38 | 39 | ]; 40 | -------------------------------------------------------------------------------- /resources/lang/es/messages.php: -------------------------------------------------------------------------------- 1 | 'Por Defecto para el sitio', 6 | 'section_defaults' => 'Por defecto para la sección', 7 | 'humans_txt' => 'Humans.txt', 8 | 'reports' => 'Reportes', 9 | 'seo_reports' => 'Reportes SEO', 10 | 'generate_report' => 'Generar Reporte', 11 | 'back_to_reports' => 'Volver a reportes', 12 | 'report_is_being_generated' => 'Tu reporte está siendo generado.', 13 | 'generated' => 'Generado', 14 | 'page_details' => 'Detalles de página', 15 | 'report_no_results_text' => 'Ejecuta un reporte en tu sitio para ver lo bien que ha sido configurado, y aprender maneras de mejorarlo.', 16 | 'generate_your_first_report' => 'Generar primer reporte', 17 | 'latest_report_score' => 'Puntuación de tu último reporte', 18 | 'source_suggest_placeholder' => 'Selecciona o escribe un nombre del campo contenga el valor.', 19 | 'no_collections' => 'No hay colecciones.', 20 | 'no_taxonomies' => 'No hay taxonomias.', 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/es/settings.php: -------------------------------------------------------------------------------- 1 | 'El contenedor de imagenes es usado para cualquiera de los campos de imagen de SEO Pro.', 6 | 7 | 'og_image_dimensions' => 'Tamaños de imagen de OpenGraph', 8 | 'og_image_dimensions_instruct' => 'De acuerdo a este artículo, el tamaño de imagen idal para las etiquetas de imagen Open Graph de Facebook y Reddit es 1200x1200 pixels.', 9 | 10 | 'open_graph_image_width' => 'Ancho', 11 | 'open_graph_image_width_instruct' => 'En pixels', 12 | 13 | 'open_graph_image_height' => 'Alto', 14 | 'open_graph_image_height_instruct' => 'En pixels', 15 | 16 | 'sitemap_enabled' => 'Habilitado', 17 | 'sitemap_enabled_instruct' => 'Si está habilitado, un xml de sitemp estará disponible en la URL definida abajo.', 18 | 19 | 'sitemap_url' => 'URL del Sitemap', 20 | 'sitemap_url_instruct' => 'La localizacion del sitemap relativa a la raiz de tu página de home en el idioma por defecto.', 21 | 22 | 'sitemap_cache_length' => 'Duración de Cache', 23 | 'sitemap_cache_length_instruct' => 'Cuanto tiempo debería ser cacheado el Sitemap, en minutos.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/fr/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Activer', 6 | 'enabled_instruct' => 'Si vous désactivez cet élément, il sera exclu des rapports et empêchera tout rendu par le biais de la balise de modèle.', 7 | 8 | 'title' => 'Titre Meta', 9 | 'title_instruct' => 'Chaque URL de votre site doit avoir un titre unique, idéalement moins de 60 caractères.', 10 | 11 | 'description' => 'Description Meta', 12 | 'description_instruct' => 'Chaque URL de votre site doit avoir une description méta unique, idéalement inférieure à 160 caractères.', 13 | 14 | 'image' => 'Image réseau social', 15 | 'image_instruct' => 'Cette image est utilisée comme image de prévisualisation de réseau social.', 16 | 17 | 'sitemap' => 'Sitemap', 18 | 'sitemap_instruct' => "S'il est désactivé, cet élément n'apparaîtra pas dans le plan du site.", 19 | 20 | 'priority' => 'Sitemap: Priorité', 21 | 'priority_instruct' => 'La priorité de cette URL par rapport aux autres URL de votre site. Les valeurs valides vont de `0.0` à` 1.0`.', 22 | 23 | 'change_frequency' => 'Sitemap: Fréquence de changement', 24 | 'change_frequency_instruct' => 'Un indice pour les moteurs de recherche sur la fréquence de changement de la page.', 25 | 26 | ]; 27 | -------------------------------------------------------------------------------- /resources/lang/fr/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Meta Data', 6 | 'meta_section_instruct' => 'Chaque URL de votre site doit avoir un titre et une description uniques.', 7 | 8 | 'title' => 'Titre Meta', 9 | 'title_instruct' => 'Choisissez un champ existant à définir comme ** méta titre ** par défaut. Chaque collection et taxonomie peut également avoir son propre défaut.', 10 | 11 | 'site_name' => 'Nom du Site', 12 | 'site_name_instruct' => "Il est courant d'inclure le nom du site dans les méta titres.", 13 | 14 | 'site_name_position' => 'Position du Nom du Site', 15 | 'site_name_position_instruct' => 'Avant ou après le méta titre c\'est à vous de choisir.', 16 | 17 | 'site_name_separator' => 'Séparateur du Nom du Site', 18 | 'site_name_separator_instruct' => 'Lettre(s) entre le titre et le nom du site.', 19 | 20 | 'description' => 'Description Meta', 21 | 'description_instruct' => 'Choisissez un champ existant à définir comme ** méta description ** par défaut. Chaque collection et taxonomie peut également avoir son propre défaut.', 22 | 23 | 'image_section' => 'Open Graph', 24 | 'image_section_instruct' => 'Nous générons automatiquement la plupart des champs Open Graph à partir de vos métadonnées et de la configuration de votre site..', 25 | 26 | 'image' => 'Image', 27 | 'image_instruct' => 'Choisissez un champ d\'image par défaut pour représenter chaque URL lorsqu\'il est partagé sur les réseaux sociaux.', 28 | 29 | 'social_section' => 'Twitter', 30 | 'social_section_instruct' => 'Nous générons automatiquement la plupart des champs de la carte Twitter à partir de vos métadonnées et de la configuration de votre site..', 31 | 32 | 'twitter_handle' => 'Twitter Handle', 33 | 'twitter_handle_instruct' => '_ (Facultatif) _ Définissez le descripteur Twitter correspondant au site.', 34 | 35 | 'sitemap_section' => 'Site Map', 36 | 'sitemap_section_instruct' => 'Choisissez vos paramètres par défaut de sitemap. En cas de doute, laissez ces champs vides pour les valeurs par défaut standard.', 37 | 38 | 'priority' => 'Priorité', 39 | 'priority_instruct' => 'La priorité de cette URL par rapport aux autres URL de votre site. Les valeurs valides vont de `0.0` à` 1.0`.', 40 | 41 | 'change_frequency' => 'Fréquence de Changement', 42 | 'change_frequency_instruct' => 'Un indice pour les moteurs de recherche sur la fréquence de changement de la page.', 43 | 44 | ]; 45 | -------------------------------------------------------------------------------- /resources/lang/fr/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Activer', 6 | 'enabled_instruct' => 'Désactiver cette section l\'exclut des rapports et empêche tout rendu via la balise de modèle..', 7 | 8 | 'meta_section' => 'Meta Data', 9 | 10 | 'title' => 'Meta Title', 11 | 'title_instruct' => 'Choisissez un champ existant à définir comme ** méta titre ** par défaut de cette section.', 12 | 13 | 'description' => 'Meta Description', 14 | 'description_instruct' => 'Choisissez un champ existant à définir en tant que ** défaut ** meta description de cette section.', 15 | 16 | 'og_section' => 'Open Graph', 17 | 'og_section_instruct' => 'Nous générons automatiquement la plupart des champs Open Graph à partir de vos métadonnées et de la configuration de votre site..', 18 | 19 | 'image' => 'Image', 20 | 'image_instruct' => 'Choisissez un champ d\'image par défaut pour représenter chaque URL dans cette section lorsqu\'il est partagé sur les réseaux sociaux.', 21 | 22 | 'sitemap_section' => 'Site Map', 23 | 24 | 'sitemap' => 'Activer', 25 | 'sitemap_instruct' => 'Si cette option est désactivée, les éléments de cette section n\'apparaîtront pas dans le sitemap.', 26 | 27 | 'show_future' => 'Afficher les entrées futures', 28 | 'show_future_instruct' => 'Si cette option est désactivée, les entrées datées dans le futur ne figureront pas dans le sitemap.', 29 | 30 | 'show_past' => 'Afficher les entrées passées', 31 | 'show_past_instruct' => 'Si désactivé, les entrées datées dans le passé n\'apparaîtront pas dans le sitemap.', 32 | 33 | 'priority' => 'Priorité', 34 | 'priority_instruct' => 'La priorité de ces URL par rapport aux autres URL de votre site. Les valeurs valides vont de `0.0` à` 1.0`.', 35 | 36 | 'change_frequency' => 'Fréquence de Changement', 37 | 'change_frequency_instruct' => 'Un indice pour les moteurs de recherche sur la fréquence de changement de la page.', 38 | 39 | ]; 40 | -------------------------------------------------------------------------------- /resources/lang/fr/settings.php: -------------------------------------------------------------------------------- 1 | "Emplacement de resource utilisé par tous les champs d\'image de SEO Pro.", 6 | 7 | 'og_image_dimensions' => 'OpenGraph Dimensions d\'image', 8 | 'og_image_dimensions_instruct' => 'D\'après cet article, la taille idéal d\'image pour Facebook et Reddit Open Graph tags est 1200x1200 pixels.', 9 | 10 | 'open_graph_image_width' => 'Largeur', 11 | 'open_graph_image_width_instruct' => 'En pixels', 12 | 13 | 'open_graph_image_height' => 'Hauteur', 14 | 'open_graph_image_height_instruct' => 'En pixels', 15 | 16 | 'sitemap_enabled' => 'Activer', 17 | 'sitemap_enabled_instruct' => 'Si activé, un fichier sitemap xml sera visible a l\'URL définie ci-dessous.', 18 | 19 | 'sitemap_url' => 'Sitemap URL', 20 | 'sitemap_url_instruct' => "L'emplacement du sitemap par rapport à la racine de la page d'accueil de votre environnement local par défaut.", 21 | 22 | 'sitemap_cache_length' => 'Durée du Cache', 23 | 'sitemap_cache_length_instruct' => 'Durée du cache de la sitemap, en minutes.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/it/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Attivo', 6 | 'enabled_instruct' => 'Disattivare questo elemento lo escluderà dai report e dalla sitemap, e impedirà qualsiasi output tramite il tag template.', 7 | 8 | 'title' => 'Meta Title', 9 | 'title_instruct' => 'Ogni URL del sito dovrebbe avere un Meta Title univoco, idealmente inferiore a 60 caratteri.', 10 | 11 | 'description' => 'Meta Description', 12 | 'description_instruct' => 'Ogni URL del sito dovrebbe avere una Meta Description univoca, idealmente inferiore a 160 caratteri.', 13 | 14 | 'site_name' => 'Nome del sito', 15 | 'site_name_instruct' => 'Opzionalmente disattiva il nome del sito per questa pagina.', 16 | 17 | 'site_name_position' => 'Posizione del nome del sito', 18 | 'site_name_position_instruct' => 'Regola opzionalmente la posizione del nome del sito per questa pagina.', 19 | 20 | 'site_name_separator' => 'Separatore del nome del sito', 21 | 'site_name_separator_instruct' => 'Regola opzionalmente il separatore per questa pagina.', 22 | 23 | 'canonical_url' => 'URL canonico', 24 | 'canonical_url_instruct' => 'Ogni URL del tuo sito dovrebbe avere un URL canonico univoco.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Scegli le opzioni per il meta tag robots. noindex impedisce l’indicizzazione, nofollow impedisce la scansione dei link.', 28 | 29 | 'image' => 'Immagine social', 30 | 'image_instruct' => 'Questa immagine sarà utilizzata come anteprima sui social network.', 31 | 32 | 'twitter_handle' => 'Handle Twitter', 33 | 'twitter_handle_instruct' => 'Sovrascrivi opzionalmente l’handle Twitter per questa pagina.', 34 | 35 | 'sitemap' => 'Sitemap', 36 | 'sitemap_instruct' => 'Se disattivato, questo elemento non sarà incluso nella sitemap.', 37 | 38 | 'priority' => 'Priorità della sitemap', 39 | 'priority_instruct' => 'La priorità di questo URL rispetto agli altri del sito. Valori validi: da 0.0 a 1.0.', 40 | 41 | 'change_frequency' => 'Frequenza di aggiornamento della sitemap', 42 | 'change_frequency_instruct' => 'Suggerisce ai motori di ricerca con quale frequenza la pagina può cambiare.', 43 | 44 | ]; -------------------------------------------------------------------------------- /resources/lang/it/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Meta Dati', 6 | 'meta_section_instruct' => 'Ogni URL del tuo sito dovrebbe avere un titolo e una descrizione meta univoci.', 7 | 8 | 'title' => 'Meta Title', 9 | 'title_instruct' => 'Seleziona un campo esistente da usare come **titolo meta predefinito**. Ogni Collection e Tassonomia può avere il proprio.', 10 | 11 | 'description' => 'Meta Description', 12 | 'description_instruct' => 'Seleziona un campo esistente da usare come **descrizione meta predefinita**. Ogni Collection e Tassonomia può avere il proprio.', 13 | 14 | 'site_name' => 'Nome del sito', 15 | 'site_name_instruct' => 'È buona prassi includere il nome del sito nei titoli meta.', 16 | 17 | 'site_name_position' => 'Posizione del nome del sito', 18 | 'site_name_position_instruct' => 'Puoi scegliere se inserirlo prima o dopo il titolo meta.', 19 | 20 | 'site_name_separator' => 'Separatore del nome del sito', 21 | 'site_name_separator_instruct' => 'Il carattere o i caratteri tra il titolo e il nome del sito.', 22 | 23 | 'canonical_url' => 'URL canonico', 24 | 'canonical_url_instruct' => 'Seleziona un campo esistente da usare come **URL canonico predefinito**. Ogni Collection e Tassonomia può avere il proprio.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Scegli le opzioni per il meta tag robots. noindex impedisce l’indicizzazione, nofollow impedisce la scansione dei link.', 28 | 29 | 'image_section' => 'Open Graph', 30 | 'image_section_instruct' => 'Generiamo automaticamente la maggior parte dei campi Open Graph dai tuoi metadati e dalla configurazione del sito.', 31 | 32 | 'image' => 'Immagine', 33 | 'image_instruct' => 'Scegli un campo immagine predefinito da usare per rappresentare ciascun URL sui social.', 34 | 35 | 'social_section' => 'Twitter', 36 | 'social_section_instruct' => 'Generiamo automaticamente la maggior parte dei campi Twitter Card dai tuoi metadati e dalla configurazione del sito.', 37 | 38 | 'twitter_handle' => 'Handle Twitter', 39 | 'twitter_handle_instruct' => 'Scegli un handle Twitter predefinito associato al sito.', 40 | 41 | 'sitemap_section' => 'Sitemap', 42 | 'sitemap_section_instruct' => 'Configura le impostazioni sitemap predefinite. Se hai dubbi, lascia i campi vuoti per usare i valori standard.', 43 | 44 | 'priority' => 'Priorità', 45 | 'priority_instruct' => 'La priorità di questo URL rispetto agli altri del sito. Valori validi: da `0.0` a `1.0`.', 46 | 47 | 'change_frequency' => 'Frequenza di aggiornamento', 48 | 'change_frequency_instruct' => 'Un suggerimento per i motori di ricerca su quanto frequentemente la pagina potrebbe cambiare.', 49 | 50 | 'search_section' => 'Motori di ricerca', 51 | 'search_section_instruct' => 'Verificare il sito con i principali motori di ricerca aiuta a capire come viene indicizzato.', 52 | 53 | 'bing_verification' => 'Codice di verifica Bing', 54 | 'bing_verification_instruct' => 'Ottieni il codice di verifica su [Bing Webmaster Tools](https://www.bing.com/toolbox/webmaster).', 55 | 56 | 'google_verification' => 'Codice di verifica Google', 57 | 'google_verification_instruct' => 'Ottieni il codice di verifica su [Google Search Console](https://search.google.com/search-console).', 58 | 59 | ]; -------------------------------------------------------------------------------- /resources/lang/it/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Attivo', 6 | 'enabled_instruct' => 'Disattivando questa sezione verrà esclusa dai report e dalla sitemap, e non verrà renderizzato nulla tramite il tag template.', 7 | 8 | 'meta_section' => 'Meta Dati', 9 | 10 | 'title' => 'Meta Title', 11 | 'title_instruct' => 'Scegli un campo esistente da usare come **titolo meta predefinito** per questa sezione.', 12 | 13 | 'description' => 'Meta Description', 14 | 'description_instruct' => 'Scegli un campo esistente da usare come **descrizione meta predefinita** per questa sezione.', 15 | 16 | 'site_name' => 'Nome del sito', 17 | 'site_name_instruct' => 'Facoltativamente disattiva il nome del sito per questa sezione.', 18 | 19 | 'site_name_position' => 'Posizione del nome del sito', 20 | 'site_name_position_instruct' => 'Facoltativamente regola la posizione del nome del sito per questa sezione.', 21 | 22 | 'site_name_separator' => 'Separatore del nome del sito', 23 | 'site_name_separator_instruct' => 'Facoltativamente regola il separatore per questa sezione.', 24 | 25 | 'canonical_url' => 'URL canonico', 26 | 'canonical_url_instruct' => 'Scegli un campo esistente da usare come **URL canonico predefinito** per questa sezione.', 27 | 28 | 'robots' => 'Robots', 29 | 'robots_instruct' => 'Scegli le opzioni per il meta tag robots. noindex impedisce l’indicizzazione, nofollow impedisce la scansione dei link.', 30 | 31 | 'og_section' => 'Open Graph', 32 | 'og_section_instruct' => 'Generiamo automaticamente la maggior parte dei campi Open Graph dai metadati e dalla configurazione del sito.', 33 | 34 | 'image' => 'Immagine', 35 | 'image_instruct' => 'Scegli un campo immagine predefinito per rappresentare ogni URL in questa sezione quando viene condiviso sui social network.', 36 | 37 | 'twitter_handle' => 'Handle Twitter', 38 | 'twitter_handle_instruct' => 'Scegli un handle Twitter predefinito associato a questa sezione.', 39 | 40 | 'sitemap_section' => 'Sitemap', 41 | 42 | 'sitemap' => 'Sitemap', 43 | 'sitemap_instruct' => 'Se disattivato, gli elementi di questa sezione non appariranno nella sitemap.', 44 | 45 | 'show_future' => 'Mostra contenuti futuri', 46 | 'show_future_instruct' => 'Se disattivato, le voci datate nel futuro non appariranno nella sitemap.', 47 | 48 | 'show_past' => 'Mostra contenuti passati', 49 | 'show_past_instruct' => 'Se disattivato, le voci datate nel passato non appariranno nella sitemap.', 50 | 51 | 'priority' => 'Priorità', 52 | 'priority_instruct' => 'La priorità di questi URL rispetto agli altri nel sito. Valori validi da `0.0` a `1.0`.', 53 | 54 | 'change_frequency' => 'Frequenza di aggiornamento', 55 | 'change_frequency_instruct' => 'Suggerimento per i motori di ricerca sulla frequenza di aggiornamento prevista per le pagine in questa sezione.', 56 | 57 | ]; -------------------------------------------------------------------------------- /resources/lang/it/settings.php: -------------------------------------------------------------------------------- 1 | "Il contenitore media usato per i campi immagine di SEO Pro.", 6 | 7 | 'og_image_dimensions' => 'Dimensioni immagine OpenGraph', 8 | 'og_image_dimensions_instruct' => 'Secondo questo articolo, la dimensione ideale per Facebook e Reddit è 1200x1200 pixel.', 9 | 10 | 'open_graph_image_width' => 'Larghezza', 11 | 'open_graph_image_width_instruct' => 'In pixel', 12 | 13 | 'open_graph_image_height' => 'Altezza', 14 | 'open_graph_image_height_instruct' => 'In pixel', 15 | 16 | 'sitemap_enabled' => 'Attiva', 17 | 'sitemap_enabled_instruct' => 'Se attivo, il file sitemap.xml sarà accessibile all’URL definito qui sotto.', 18 | 19 | 'sitemap_url' => 'URL della Sitemap', 20 | 'sitemap_url_instruct' => "Posizione della sitemap rispetto alla root della home page della lingua predefinita.", 21 | 22 | 'sitemap_cache_length' => 'Durata della cache', 23 | 'sitemap_cache_length_instruct' => 'Per quanto tempo (in minuti) la sitemap deve essere mantenuta in cache.', 24 | 25 | ]; -------------------------------------------------------------------------------- /resources/lang/nl/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Ingeschakeld', 6 | 'enabled_instruct' => 'Het uitschakelen van dit item zorgt ervoor dat het niet meer voorkomt in rapporten en in de sitemap en voorkomt dat er iets wordt weergeven via de template tag.', 7 | 8 | 'title' => 'Metatitel', 9 | 'title_instruct' => 'Elke URL op uw site moet een unieke metatitel hebben, bij voorkeur is deze minder dan 60 tekens lang.', 10 | 11 | 'description' => 'Meta-omschrijving', 12 | 'description_instruct' => 'Elke URL op uw site moet een unieke meta-omschrijving hebben, bij voorkeur is deze minder dan 160 tekens lang.', 13 | 14 | 'site_name' => 'Sitenaam', 15 | 'site_name_instruct' => 'Optioneel de sitenaam uitschakelen voor deze pagina.', 16 | 17 | 'site_name_position' => 'Positie van de sitenaam', 18 | 'site_name_position_instruct' => 'Optioneel de positie aanpassen voor deze pagina.', 19 | 20 | 'site_name_separator' => 'Scheidingsteken van de sitenaam', 21 | 'site_name_separator_instruct' => 'Optioneel het scheidingsteken aanpassen voor deze pagina.', 22 | 23 | 'canonical_url' => 'Canonieke URL', 24 | 'canonical_url_instruct' => 'Elke URL op uw site moet een unieke canonieke URL hebben.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Opties selecteren voor de robots meta-tag. noindex voorkomt dat de pagina wordt geïndexeerd door zoekmachines. nofollow voorkomt dat zoekmachines links crawlen.', 28 | 29 | 'image' => 'Sociale Afbeelding', 30 | 'image_instruct' => 'Deze afbeelding wordt gebruikt in de preview op een sociale netwerken.', 31 | 32 | 'twitter_handle' => 'Twitter-handle', 33 | 'twitter_handle_instruct' => 'Optioneel de Twitter-handle overschrijven voor deze pagina.', 34 | 35 | 'sitemap' => 'Sitemap', 36 | 'sitemap_instruct' => 'Indien uitgeschakeld, wordt dit item niet weergegeven in de sitemap.', 37 | 38 | 'priority' => 'Sitemap: Prioriteit', 39 | 'priority_instruct' => "De prioriteit van deze URL ten opzichte van andere URL's op uw site. Geldige waarden zijn of zitten tussen '0.0' tot '1.0'.", 40 | 41 | 'change_frequency' => 'Sitemap: Updatefrequentie', 42 | 'change_frequency_instruct' => 'Een instructie voor zoekmachines over hoe vaak de pagina waarschijnlijk geüpdatet zal worden.', 43 | 44 | ]; 45 | -------------------------------------------------------------------------------- /resources/lang/nl/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Metadata', 6 | 'meta_section_instruct' => 'Iedere URL op uw website hoort een unieke metatitel en meta-omschrijving te hebben.', 7 | 8 | 'title' => 'Metatitel', 9 | 'title_instruct' => 'Kies een bestaand veld om deze te gebruiken als de **standaard** metatitel. Iedere collectie en taxonomie kan zijn eigen standaardinstelling hebben.', 10 | 11 | 'description' => 'Meta-omschrijving', 12 | 'description_instruct' => 'Kies een bestaand veld om te gebruiken als de **standaard** meta-omschrijving. Iedere collectie en taxonomie kan zijn eigen standaardinstelling hebben.', 13 | 14 | 'site_name' => 'Sitenaam', 15 | 'site_name_instruct' => 'Het is gebruikelijk om uw sitenaam te gebruiken in metatitels.', 16 | 17 | 'site_name_position' => 'Sitenaam positie', 18 | 'site_name_position_instruct' => 'Voor of achter de metatitel.', 19 | 20 | 'site_name_separator' => 'Sitenaam scheidingsteken', 21 | 'site_name_separator_instruct' => 'Het teken / de tekens tussen de titel en de sitenaam.', 22 | 23 | 'canonical_url' => 'Canonieke URL', 24 | 'canonical_url_instruct' => 'Kies een bestaand veld om in te stellen als uw **standaard** canonieke URL. Elke collectie en taxonomie kan ook zijn eigen standaard hebben.', 25 | 26 | 'robots' => 'Robots', 27 | 'robots_instruct' => 'Kies opties voor de robots meta-tag. noindex voorkomt dat de pagina wordt geïndexeerd door zoekmachines. nofollow voorkomt dat zoekmachines links crawlen.', 28 | 29 | 'image_section' => 'Open Graph', 30 | 'image_section_instruct' => 'We genereren automatisch de meeste Open Graph-velden op basis van uw metadata en siteconfiguratie.', 31 | 32 | 'image' => 'Afbeelding', 33 | 'image_instruct' => 'Kies een standaard afbeeldingenveld die bij het delen van iedere willekeurige URL op sociale netwerken gebruikt kan worden.', 34 | 35 | 'social_section' => 'Twitter', 36 | 'social_section_instruct' => 'We genereren automatisch de meeste Twitter kaartvelden op basis van uw metadata en siteconfiguratie.', 37 | 38 | 'twitter_handle' => 'Twitter gebruikersnaam', 39 | 'twitter_handle_instruct' => '_(Optioneel)_ Stel de gebruikersnaam van Twitter in die bij uw site hoort..', 40 | 41 | 'sitemap_section' => 'Sitemap', 42 | 'sitemap_section_instruct' => 'Kies uw standaard sitemapinstellingen. Als uw het niet zeker weet, laat deze velden dan leeg en gebruik de standaardinstellingen.', 43 | 44 | 'priority' => 'Prioriteit', 45 | 'priority_instruct' => "De prioriteit van deze URL ten opzichte van andere URL's op uw site. Geldige waarden zijn of zitten tussen '0.0' tot '1.0'.", 46 | 47 | 'change_frequency' => 'Updatefrequentie', 48 | 'change_frequency_instruct' => 'Een instructie voor zoekmachines over hoe vaak paginawaarschijnlijk geüpdatet zal worden.', 49 | 50 | 'search_section' =>'Search Engines', 51 | 'search_section_instruct' => 'Het verifiëren van uw site bij populaire zoekmachines helpt u bij het volgen van hoe goed ze uw site crawlen.', 52 | 53 | 'bing_verification' => 'Bing Verificatiecode', 54 | 'bing_verification_instruct' => 'Haal uw Bing verificatiecode op in [Bing Webmaster Tools](https://www.bing.com/toolbox/webmaster).', 55 | 56 | 'google_verification' => 'Google Verificatiecode', 57 | 'google_verification_instruct' => 'Haal uw Google verificatiecode op in [Google Search Console](https://search.google.com/search-console).', 58 | 59 | ]; 60 | -------------------------------------------------------------------------------- /resources/lang/nl/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Ingeschakeld', 6 | 'enabled_instruct' => 'Het uitschakelen van dit gedeelte zorgt ervoor dat het niet meer voorkomt in rapporten en in de sitemap en voorkomt dat er iets wordt weergeven via de template tag.', 7 | 8 | 'meta_section' => 'Metadata', 9 | 10 | 'title' => 'Metatitel', 11 | 'title_instruct' => 'Kies een bestaand veld om te gebruiken als de **standaard** metatitel van dit gedeelte.', 12 | 13 | 'description' => 'Meta-omschrijving', 14 | 'description_instruct' => 'Kies een bestaand veld om te gebruiken als de **standaard** meta-omschrijving van dit gedeelte.', 15 | 16 | 'site_name' => 'Sitenaam', 17 | 'site_name_instruct' => 'Schakel optioneel de sitenaam uit voor dit gedeelte.', 18 | 19 | 'site_name_position' => 'Sitenaam positie', 20 | 'site_name_position_instruct' => 'Pas optioneel de positie aan voor dit gedeelte.', 21 | 22 | 'site_name_separator' => 'Sitenaam scheidingsteken', 23 | 'site_name_separator_instruct' => 'Pas optioneel het scheidingsteken aan voor dit gedeelte.', 24 | 25 | 'canonical_url' => 'Canonical URL', 26 | 'canonical_url_instruct' => 'Kies een bestaand veld om in te stellen als de **standaard** canonical URL van dit gedeelte.', 27 | 28 | 'robots' => 'Robots', 29 | 'robots_instruct' => 'Kies opties voor de robots meta-tag. noindex voorkomt dat de pagina geïndexeerd wordt door zoekmachines. nofollow voorkomt dat zoekmachines links crawlen.', 30 | 31 | 'og_section' => 'Open Graph', 32 | 'og_section_instruct' => 'We genereren automatisch de meeste Open Graph-velden op basis van uw metadata en siteconfiguratie.', 33 | 34 | 'image' => 'Afbeelding', 35 | 'image_instruct' => 'Kies een standaard afbeeldingenveld die bij het delen van iedere willekeurige URL op sociale netwerken gebruikt kan worden.', 36 | 37 | 'twitter_handle' => 'Twitter-handle', 38 | 'twitter_handle_instruct' => 'Kies een standaard twitter-handle die overeenkomt met dit gedeelte.', 39 | 40 | 'sitemap_section' => 'Sitemap', 41 | 42 | 'sitemap' => 'Sitemap', 43 | 'sitemap_instruct' => 'Indien uitgeschakeld, worden items in dit gedeelte niet in de sitemap weergegeven.', 44 | 45 | 'show_future' => 'Toon Toekomstige Inhoud', 46 | 'show_future_instruct' => 'Indien uitgeschakeld, zal in de toekomst gedateerde inhoud niet in de sitemap voorkomen.', 47 | 48 | 'show_past' => 'Toon Verouderde Inhoud', 49 | 'show_past_instruct' => 'Indien uitgeschakeld, zal in het verleden gedateerde inhoud niet in de sitemap voorkomen.', 50 | 51 | 'priority' => 'Prioriteit', 52 | 'priority_instruct' => "De prioriteit van deze URL ten opzichte van andere URL's op uw site. Geldige waarden zijn of zitten tussen '0.0' tot '1.0'.", 53 | 54 | 'change_frequency' => 'Updatefrequentie', 55 | 'change_frequency_instruct' => "Een instructie voor zoekmachines over hoe vaak pagina's in dit gedeelte waarschijnlijk geüpdatet zullen worden.", 56 | 57 | ]; 58 | -------------------------------------------------------------------------------- /resources/lang/nl/settings.php: -------------------------------------------------------------------------------- 1 | 'De bestandcontainer die gebruikt moet worden voor afbeeldingsvelden van SEO Pro.', 6 | 7 | 'og_image_dimensions' => 'OpenGraph Afbeeldingsformaat', 8 | 'og_image_dimensions_instruct' => 'Volgens dit arikel, is het ideale afbeeldingsformaat voor Facebook en Reddit Open Graph 1200x1200 pixels.', 9 | 10 | 'open_graph_image_width' => 'Breedte', 11 | 'open_graph_image_width_instruct' => 'In pixels', 12 | 13 | 'open_graph_image_height' => 'Hoogte', 14 | 'open_graph_image_height_instruct' => 'In pixels', 15 | 16 | 'sitemap_enabled' => 'Ingeschakeld', 17 | 'sitemap_enabled_instruct' => 'Indien ingeschakeld, zal een sitemap-xml-bestand zichtbaar zijn op de hieronder gedefinieerde URL.', 18 | 19 | 'sitemap_url' => 'Sitemap-URL', 20 | 'sitemap_url_instruct' => 'De locatie van de sitemap ten opzichte van de hoofdmap van de homepage van de standaardtaal.', 21 | 22 | 'sitemap_cache_length' => 'Cache Lengte', 23 | 'sitemap_cache_length_instruct' => 'Hoe lang (in minuten) de sitemap in de cache moet worden bewaard.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/lang/pt/fieldsets/content.php: -------------------------------------------------------------------------------- 1 | 'Ativado', 6 | 'enabled_instruct' => 'Desativando este item irá excluí-lo dos relatórios e do sitemap e impedir que qualquer coisa seja renderizada por meio da tag de modelo.', 7 | 8 | 'title' => 'Meta Título', 9 | 'title_instruct' => 'Cada URL em seu site deve ter um Meta Título exclusivo, idealmente com menos de 60 caracteres.', 10 | 11 | 'description' => 'Meta Descrição', 12 | 'description_instruct' => 'Cada URL em seu site deve ter uma Meta Descrição exclusiva, idealmente com menos de 160 caracteres.', 13 | 14 | 'image' => 'Imagem Social', 15 | 'image_instruct' => 'Esta imagem é usada como uma imagem de visualização nas redes sociais.', 16 | 17 | 'sitemap' => 'Sitemap', 18 | 'sitemap_instruct' => 'Se desativado, este item não será exibido no sitemap.', 19 | 20 | 'priority' => 'Sitemap: Prioridade', 21 | 'priority_instruct' => 'A prioridade deste URL em relação a outros URLs no seu site. Os valores válidos variam de `0.0` a `1.0`.', 22 | 23 | 'change_frequency' => 'Sitemap: Frequência de mudança', 24 | 'change_frequency_instruct' => 'Uma dica para os mecanismos de pesquisa sobre a frequência com que se pode alterar uma página.', 25 | 26 | ]; 27 | -------------------------------------------------------------------------------- /resources/lang/pt/fieldsets/defaults.php: -------------------------------------------------------------------------------- 1 | 'Meta Dados', 6 | 'meta_section_instruct' => 'Cada URL em seu site deve ter um título e uma descrição exclusivos.', 7 | 8 | 'title' => 'Meta Título', 9 | 'title_instruct' => 'Escolha um campo existente para definir como seu meta título **padrão**. Cada coleção e taxonomia também podem ter o seu próprio padrão.', 10 | 11 | 'site_name' => 'Nome do Site', 12 | 'site_name_instruct' => 'É uma prática comum incluir o nome do site meta em títulos.', 13 | 14 | 'site_name_position' => 'Posição do Nome do Site', 15 | 'site_name_position_instruct' => 'Cabe a ti escolher antes ou depois meta do título.', 16 | 17 | 'site_name_separator' => 'Separador de Nome do Site', 18 | 'site_name_separator_instruct' => 'O(s) caracter(es) entre o título e o nome do site.', 19 | 20 | 'description' => 'Meta Descrição', 21 | 'description_instruct' => 'Escolha um campo existente para definir como sua meta descrição **padrão**. Cada coleção e taxonomia também podem ter o seu próprio padrão.', 22 | 23 | 'image_section' => 'Open Graph', 24 | 'image_section_instruct' => 'Nós geramos automaticamente a maioria dos campos do Open Graph a partir dos seus metadados e configuração do site.', 25 | 26 | 'image' => 'Imagem', 27 | 'image_instruct' => 'Escolha um campo de imagem padrão para representar cada URL quando partilhado nas redes sociais.', 28 | 29 | 'social_section' => 'Twitter', 30 | 'social_section_instruct' => 'Nós geramos automaticamente a maioria dos campos do Twitter Card a partir dos seus metadados e configuração do site.', 31 | 32 | 'twitter_handle' => 'Identificador Twitter', 33 | 'twitter_handle_instruct' => '_(Opcional)_ Definir o identificador do Twitter que corresponde ao site.', 34 | 35 | 'sitemap_section' => 'Site Map', 36 | 'sitemap_section_instruct' => 'Escolha suas configurações padrão de sitemap. Se não tiver a certeza, deixe em branco para os valores padrão.', 37 | 38 | 'priority' => 'Prioridade', 39 | 'priority_instruct' => 'A prioridade deste URL em relação a outros URLs no seu site. Os valores válidos variam de `0.0` a `1.0`.', 40 | 41 | 'change_frequency' => 'Frequência de Mudança', 42 | 'change_frequency_instruct' => 'Uma dica para os mecanismos de pesquisa sobre a frequência com que se pode alterar uma página.', 43 | 44 | 'search_section' => 'Ferramentas do Webmaster', 45 | 'search_section_instruct' => 'A verificação do seu website com os mecanismos de pesquisa populares ajudará a acompanhar o desempenho do rastreamento do mesmo.', 46 | 47 | 'bing_verification' => 'Código de Verificação do Bing', 48 | 'bing_verification_instruct' => 'Obtenha o seu código de verificação do Bing em [Bing Webmaster Tools](https://www.bing.com/toolbox/webmaster).', 49 | 50 | 'google_verification' => 'Código de Verificação do Google', 51 | 'google_verification_instruct' => 'Obtenha o seu código de verificação do Google em [Google Search Console](https://search.google.com/search-console).', 52 | 53 | ]; 54 | -------------------------------------------------------------------------------- /resources/lang/pt/fieldsets/sections.php: -------------------------------------------------------------------------------- 1 | 'Ativado', 6 | 'enabled_instruct' => 'Desativando esta seção irá excluí-la dos relatórios e do sitemap e impedir que qualquer coisa seja renderizada por meio da tag de modelo.', 7 | 8 | 'meta_section' => 'Meta Dados', 9 | 10 | 'title' => 'Meta Título', 11 | 'title_instruct' => 'Escolha um campo existente para definir como meta título **padrão** desta seção.', 12 | 13 | 'description' => 'Meta Descrição', 14 | 'description_instruct' => 'Escolha um campo existente para definir como meta descrição **padrão** da seção.', 15 | 16 | 'og_section' => 'Open Graph', 17 | 'og_section_instruct' => 'Nós geramos automaticamente a maioria dos campos do Open Graph a partir dos seus metadados e configuração do site.', 18 | 19 | 'image' => 'Imagem', 20 | 'image_instruct' => 'Escolha um campo de imagem padrão para representar cada URL quando partilhado nas redes sociais.', 21 | 22 | 'sitemap_section' => 'Site Map', 23 | 24 | 'sitemap' => 'Ativado', 25 | 'sitemap_instruct' => 'Se desativado, os itens desta seção não aparecerão no sitemap.', 26 | 27 | 'show_future' => 'Mostrar Entradas Futuras', 28 | 'show_future_instruct' => 'Se desativado, as entradas com data futura não aparecerão no sitemap.', 29 | 30 | 'show_past' => 'Mostrar Entradas Anteriores', 31 | 'show_past_instruct' => 'Se desativado, as entradas com datas anteriores não aparecerão no sitemap.', 32 | 33 | 'priority' => 'Prioridade', 34 | 'priority_instruct' => 'A prioridade deste URL em relação a outros URLs no seu site. Os valores válidos variam de `0.0` a `1.0`.', 35 | 36 | 'change_frequency' => 'Frequência de Mudança', 37 | 'change_frequency_instruct' => 'Uma dica para os mecanismos de pesquisa sobre a frequência com que se pode alterar uma página.', 38 | 39 | ]; 40 | -------------------------------------------------------------------------------- /resources/lang/pt/messages.php: -------------------------------------------------------------------------------- 1 | 'Definições do Site', 6 | 'section_defaults' => 'Definições de Seção', 7 | 'humans_txt' => 'Humans.txt', 8 | 'reports' => 'Relatórios', 9 | 'seo_reports' => 'Relatórios do SEO', 10 | 'generate_report' => 'Gerar Relatórios', 11 | 'back_to_reports' => 'Voltar para Relatórios', 12 | 'report_is_being_generated' => 'O seu relatório está a ser gerado.', 13 | 'generated' => 'Gerado', 14 | 'page_details' => 'Detalhes da Página', 15 | 'report_no_results_text' => 'Crie um relatório no seu site para ver como ele foi configurado e aprenda maneiras de melhorar.', 16 | 'generate_your_first_report' => 'Gerar o seu primeiro relatório', 17 | 'latest_report_score' => 'Pontuação dos Últimos Relatórios', 18 | 'source_suggest_placeholder' => 'Selecione ou digite um nome de campo contendo o valor.', 19 | 'no_collections' => 'Não existem coleções.', 20 | 'no_taxonomies' => 'Não existem taxonomias.', 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /resources/lang/pt/settings.php: -------------------------------------------------------------------------------- 1 | 'Biblioteca de arquivos usada para qualquer um dos campos de imagem do SEO Pro.', 6 | 7 | 'og_image_dimensions' => 'Dimensões da imagem OpenGraph', 8 | 'og_image_dimensions_instruct' => 'De acordo com este artigo, o tamanho de imagem ideal para as etiquetas Facebook e Reddit Open Graph é de 1200x1200 pixels.', 9 | 10 | 'open_graph_image_width' => 'Largura', 11 | 'open_graph_image_width_instruct' => 'Em pixels', 12 | 13 | 'open_graph_image_height' => 'Altura', 14 | 'open_graph_image_height_instruct' => 'Em pixels', 15 | 16 | 'sitemap_enabled' => 'Ativado', 17 | 'sitemap_enabled_instruct' => 'Se ativado, um arquivo xml de sitemap será visível no URL definido abaixo.', 18 | 19 | 'sitemap_url' => 'URL do Sitemap', 20 | 'sitemap_url_instruct' => "The location of the sitemap relative to the root of your default locale's home page.", 21 | 22 | 'sitemap_cache_length' => 'Comprimento do Cache', 23 | 'sitemap_cache_length_instruct' => 'Quanto tempo o sitemap deve ficar armazenado em cache, em minutos.', 24 | 25 | ]; 26 | -------------------------------------------------------------------------------- /resources/views/edit.blade.php: -------------------------------------------------------------------------------- 1 | @extends('statamic::layout') 2 | 3 | @section('content') 4 | 5 | @if (isset($breadcrumbTitle) && isset($breadcrumbUrl)) 6 |
7 | @include('statamic::partials.breadcrumb', [ 8 | 'url' => $breadcrumbUrl, 9 | 'title' => $breadcrumbTitle 10 | ]) 11 |

@yield('title')

12 |
13 | @endif 14 | 15 | 22 | 23 | @include('statamic::partials.docs-callout', [ 24 | 'topic' => 'SEO Pro', 25 | 'url' => 'https://statamic.com/addons/statamic/seo-pro' 26 | ]) 27 | @stop 28 | -------------------------------------------------------------------------------- /resources/views/generated/humans.antlers.html: -------------------------------------------------------------------------------- 1 | /* TEAM */ 2 | 3 | Creator: {{ site_name }} 4 | URL: {{ home_url }} 5 | Description: {{ description }} 6 | 7 | /* THANKS */ 8 | 9 | Statamic: https://statamic.com 10 | 11 | /* SITE */ 12 | 13 | Standards: HTML5, CSS3 14 | Components: Statamic, Laravel, PHP, JavaScript 15 | -------------------------------------------------------------------------------- /resources/views/generated/sitemap.antlers.html: -------------------------------------------------------------------------------- 1 | {{ xml_header }} 2 | 3 | {{ pages }} 4 | 5 | {{ loc }} 6 | {{ lastmod }} 7 | {{ changefreq }} 8 | {{ priority }} 9 | 10 | {{ /pages }} 11 | 12 | -------------------------------------------------------------------------------- /resources/views/generated/sitemap_index.antlers.html: -------------------------------------------------------------------------------- 1 | {{ xml_header }} 2 | 3 | {{ sitemaps }} 4 | 5 | {{ url }} 6 | 7 | {{ /sitemaps }} 8 | 9 | -------------------------------------------------------------------------------- /resources/views/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('statamic::layout') 2 | @section('title', 'SEO Pro') 3 | 4 | @section('content') 5 | 6 |
7 |

{{ 'SEO Pro' }}

8 |
9 | 10 |
11 |
12 | @can('view seo reports') 13 | 14 |
15 | @cp_svg('icons/light/charts') 16 |
17 |
18 |

{{ __('seo-pro::messages.reports') }}

19 |

{{ __('seo-pro::messages.seo_reports_description') }}

20 |
21 |
22 | @endcan 23 | @can('edit seo site defaults') 24 | 25 |
26 | @cp_svg('icons/light/hammer-wrench') 27 |
28 |
29 |

{{ __('seo-pro::messages.site_defaults') }}

30 |

{{ __('seo-pro::messages.site_defaults_description') }}

31 |
32 |
33 | @endcan 34 | @can('edit seo section defaults') 35 | 36 |
37 | @cp_svg('icons/light/hammer-wrench') 38 |
39 |
40 |

{{ __('seo-pro::messages.section_defaults') }}

41 |

{{ __('seo-pro::messages.section_defaults_description') }}

42 |
43 |
44 | @endcan 45 |
46 |
47 | 48 | @include('statamic::partials.docs-callout', [ 49 | 'topic' => 'SEO Pro', 50 | 'url' => 'https://statamic.com/addons/statamic/seo-pro' 51 | ]) 52 | 53 | @endsection 54 | -------------------------------------------------------------------------------- /resources/views/reports/index.blade.php: -------------------------------------------------------------------------------- 1 | @extends('statamic::layout') 2 | @section('title', __('seo-pro::messages.seo_reports')) 3 | 4 | @section('content') 5 | 6 |
7 |

{{ __('seo-pro::messages.reports') }}

8 | {{ __('seo-pro::messages.generate_report') }} 9 |
10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | @foreach($reports as $report) 22 | 23 | 32 | 35 | 38 | 41 | @can('delete seo reports') 42 | 54 | @endcan 55 | 56 | @endforeach 57 | 58 |
Site ScoreGeneratedActionable PagesTotal Pages Crawled
24 |
25 | 30 |
31 |
33 | {{ $report->date()->diffForHumans() }} 34 | 36 | {{ $report->pagesActionable() ?? 'N/A' }} 37 | 39 | {{ $report->pagesCrawled() }} 40 | 43 | 44 | 45 | 51 | 52 | 53 |
59 |
60 | 61 | @include('statamic::partials.docs-callout', [ 62 | 'topic' => 'SEO Pro', 63 | 'url' => 'https://statamic.com/addons/statamic/seo-pro' 64 | ]) 65 | 66 | @stop 67 | -------------------------------------------------------------------------------- /resources/views/reports/show.blade.php: -------------------------------------------------------------------------------- 1 | @extends('statamic::layout') 2 | @section('title', __('seo-pro::messages.seo_reports')) 3 | 4 | @section('content') 5 | 6 | @include('statamic::partials.breadcrumb', [ 7 | 'url' => cp_route('seo-pro.reports.index'), 8 | 'title' => __('seo-pro::messages.reports'), 9 | ]) 10 | 11 | 16 | 17 | @include('statamic::partials.docs-callout', [ 18 | 'topic' => 'SEO Pro', 19 | 'url' => 'https://statamic.com/addons/statamic/seo-pro' 20 | ]) 21 | 22 | @stop 23 | -------------------------------------------------------------------------------- /resources/views/sections.blade.php: -------------------------------------------------------------------------------- 1 | @extends('statamic::layout') 2 | @section('title', __('seo-pro::messages.section_defaults')) 3 | 4 | @section('content') 5 | 6 |
7 |

{{ __('seo-pro::messages.section_defaults') }}

8 |
9 | 10 | @if (Statamic\Facades\Collection::all()->count()) 11 |

{{ __('Collections') }}

12 |
13 | 14 | @foreach (Statamic\Facades\Collection::all() as $collection) 15 | 16 | 22 | 23 | @endforeach 24 |
17 |
18 |
@cp_svg('icons/light/content-writing')
19 | {{ $collection->title() }} 20 |
21 |
25 |
26 | @endif 27 | 28 | @if (Statamic\Facades\Taxonomy::all()->count()) 29 |

{{ __('Taxonomies') }}

30 |
31 | 32 | @foreach (Statamic\Facades\Taxonomy::all() as $taxonomy) 33 | 34 | 40 | 41 | @endforeach 42 |
35 |
36 |
@cp_svg('icons/light/tags')
37 | {{ $taxonomy->title() }} 38 |
39 |
43 |
44 | @endif 45 | 46 | @include('statamic::partials.docs-callout', [ 47 | 'topic' => 'SEO Pro', 48 | 'url' => 'https://statamic.com/addons/statamic/seo-pro' 49 | ]) 50 | 51 | @stop 52 | -------------------------------------------------------------------------------- /resources/views/widget.blade.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |

SEO Pro

4 | 5 | {{ __('seo-pro::messages.reports') }} 6 | 7 |
8 |
9 | @if ($report) 10 |
15 | {{ $report->score() }}% 16 |
17 |

18 | {{ __('seo-pro::messages.latest_report_score') }} 19 |

20 | @else 21 |
22 |

23 | {{ __('seo-pro::messages.report_no_results_text') }} 24 |

25 | 26 | {{ __('seo-pro::messages.generate_your_first_report') }} 27 | 28 |
29 | @endif 30 |
31 |
32 | -------------------------------------------------------------------------------- /routes/cp.php: -------------------------------------------------------------------------------- 1 | name('seo-pro.index'); 6 | Route::get('seo-pro/reports', [Controllers\ReportController::class, 'index'])->name('seo-pro.reports.index'); 7 | Route::get('seo-pro/reports/create', [Controllers\ReportController::class, 'create'])->name('seo-pro.reports.create'); 8 | Route::get('seo-pro/reports/{seo_pro_report}', [Controllers\ReportController::class, 'show'])->name('seo-pro.reports.show'); 9 | Route::get('seo-pro/reports/{seo_pro_report}/pages', [Controllers\ReportPagesController::class, 'index'])->name('seo-pro.reports.pages.index'); 10 | Route::delete('seo-pro/reports/{seo_pro_report}', [Controllers\ReportController::class, 'destroy'])->name('seo-pro.reports.destroy'); 11 | 12 | Route::get('seo-pro/site-defaults/edit', [Controllers\SiteDefaultsController::class, 'edit'])->name('seo-pro.site-defaults.edit'); 13 | Route::post('seo-pro/site-defaults', [Controllers\SiteDefaultsController::class, 'update'])->name('seo-pro.site-defaults.update'); 14 | 15 | Route::view('seo-pro/section-defaults', 'seo-pro::sections')->name('seo-pro.section-defaults.index'); 16 | Route::get('seo-pro/section-defaults/collections/{seo_pro_collection}/edit', [Controllers\CollectionDefaultsController::class, 'edit'])->name('seo-pro.section-defaults.collections.edit'); 17 | Route::post('seo-pro/section-defaults/collections/{seo_pro_collection}', [Controllers\CollectionDefaultsController::class, 'update'])->name('seo-pro.section-defaults.collections.update'); 18 | Route::get('seo-pro/section-defaults/taxonomies/{seo_pro_taxonomy}/edit', [Controllers\TaxonomyDefaultsController::class, 'edit'])->name('seo-pro.section-defaults.taxonomies.edit'); 19 | Route::post('seo-pro/section-defaults/taxonomies/{seo_pro_taxonomy}', [Controllers\TaxonomyDefaultsController::class, 'update'])->name('seo-pro.section-defaults.taxonomies.update'); 20 | -------------------------------------------------------------------------------- /routes/web.php: -------------------------------------------------------------------------------- 1 | name('statamic.seo-pro.sitemap.page.show'); 7 | Route::get(config('statamic.seo-pro.humans.url'), [Controllers\HumansController::class, 'show']); 8 | -------------------------------------------------------------------------------- /src/Blueprint.php: -------------------------------------------------------------------------------- 1 | 'entry', 11 | Events\TermBlueprintFound::class => 'term', 12 | ]; 13 | 14 | protected $blueprint; 15 | protected $data; 16 | 17 | protected static $addingField = false; 18 | 19 | /** 20 | * Instantiate blueprint found event handler. 21 | * 22 | * @param mixed $event 23 | */ 24 | public function __construct($event) 25 | { 26 | $this->blueprint = $event->blueprint; 27 | $this->data = $this->getEventData($event); 28 | } 29 | 30 | /** 31 | * Instantiate blueprint found event handler. 32 | * 33 | * @param mixed $event 34 | * @return static 35 | */ 36 | public static function on($event) 37 | { 38 | return new static($event); 39 | } 40 | 41 | /** 42 | * Ensure SEO section and fields are added to (or removed from) blueprint. 43 | * 44 | * @param bool $isEnabled 45 | */ 46 | public function ensureSeoFields($isEnabled = true) 47 | { 48 | $isEnabled 49 | ? $this->addSeoFields() 50 | : $this->removeSeoFields(); 51 | } 52 | 53 | /** 54 | * Add SEO section and fields to blueprint. 55 | */ 56 | public function addSeoFields() 57 | { 58 | if (static::$addingField) { 59 | return; 60 | } 61 | 62 | static::$addingField = true; 63 | 64 | $this->blueprint->ensureFieldInTab('seo', [ 65 | 'type' => 'seo_pro', 66 | 'listable' => false, 67 | 'display' => 'SEO', 68 | 'localizable' => true, 69 | ], 'SEO'); 70 | 71 | static::$addingField = false; 72 | } 73 | 74 | /** 75 | * Remove SEO section and fields from blueprint. 76 | */ 77 | public function removeSeoFields() 78 | { 79 | $this->blueprint->removeTab('SEO'); 80 | } 81 | 82 | /** 83 | * Get event data. 84 | * 85 | * @param mixed $event 86 | * @return mixed 87 | */ 88 | protected function getEventData($event) 89 | { 90 | $eventClass = get_class($event); 91 | 92 | $dataProperty = static::DATA_PROPERTY[$eventClass]; 93 | 94 | return $event->{$dataProperty}; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/Commands/GenerateReportCommand.php: -------------------------------------------------------------------------------- 1 | line('Generating...'); 35 | 36 | $id = $this->option('report'); 37 | 38 | $report = Report::create($id)->generate(); 39 | 40 | $this->info("Report [{$report->id()}] generated."); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Directives/SeoProDirective.php: -------------------------------------------------------------------------------- 1 | isMissingContext($context)) { 13 | $context = array_merge( 14 | $this->getContextFromCurrentRouteData(), 15 | $this->getContextFromCascade() 16 | ); 17 | } 18 | 19 | return $this 20 | ->setContext($context) 21 | ->setParameters([]) 22 | ->$tag(); 23 | } 24 | 25 | protected function isMissingContext($context) 26 | { 27 | return ! isset($context['current_template']); 28 | } 29 | 30 | protected function getContextFromCascade() 31 | { 32 | $cascade = Cascade::instance(); 33 | 34 | // If the cascade has not yet been hydrated, ensure it is hydrated. 35 | // This is important for people using custom route/controller/view implementations. 36 | if (empty($cascade->toArray())) { 37 | $cascade->hydrate(); 38 | } 39 | 40 | return $cascade->toArray(); 41 | } 42 | 43 | protected function getContextFromCurrentRouteData() 44 | { 45 | return app('router')->current()->parameter('data') ?? []; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Events/SeoProSiteDefaultsSaved.php: -------------------------------------------------------------------------------- 1 | defaults = $defaults; 15 | } 16 | 17 | public function commitMessage() 18 | { 19 | return __('SEO Pro site defaults saved', [], config('statamic.git.locale')); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Fieldtypes/Rules/SourceFieldRule.php: -------------------------------------------------------------------------------- 1 | validate($attribute, $value['value'], $fail); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Fieldtypes/SeoProFieldtype.php: -------------------------------------------------------------------------------- 1 | false]; 23 | } 24 | 25 | return $this->fields()->addValues($data ?? [])->preProcess()->values()->all(); 26 | } 27 | 28 | public function preload() 29 | { 30 | return [ 31 | 'fields' => $this->fieldConfig(), 32 | 'meta' => $this->fields()->addValues($this->field->value())->meta(), 33 | ]; 34 | } 35 | 36 | public function process($data) 37 | { 38 | if (! Arr::get($data, 'enabled')) { 39 | return false; 40 | } 41 | 42 | $values = Arr::removeNullValues( 43 | $this->fields()->addValues($data)->process()->values()->all() 44 | ); 45 | 46 | return Arr::except($values, 'enabled'); 47 | } 48 | 49 | protected function fields() 50 | { 51 | return new BlueprintFields($this->fieldConfig()); 52 | } 53 | 54 | protected function fieldConfig() 55 | { 56 | $parent = $this->field()->parent(); 57 | 58 | if (! ($parent instanceof Entry || $parent instanceof Term)) { 59 | $parent = null; 60 | } 61 | 62 | return SeoProFields::new($parent ?? null)->getConfig(); 63 | } 64 | 65 | public function extraRules(): array 66 | { 67 | $rules = $this 68 | ->fields() 69 | ->addValues((array) $this->field->value()) 70 | ->validator() 71 | ->rules(); 72 | 73 | return collect($rules)->mapWithKeys(function ($rules, $handle) { 74 | return [$this->field->handle().'.'.$handle => $rules]; 75 | })->all(); 76 | } 77 | 78 | public function augment($data) 79 | { 80 | if (empty($data) || ! is_iterable($data)) { 81 | return $data; 82 | } 83 | 84 | return Blueprint::make() 85 | ->setContents(['fields' => $this->fieldConfig()]) 86 | ->fields() 87 | ->addValues($data) 88 | ->augment() 89 | ->values() 90 | ->only(array_keys($data)) 91 | ->all(); 92 | } 93 | 94 | public function toGqlType() 95 | { 96 | return GraphQL::type('SeoPro'); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/GetsSectionDefaults.php: -------------------------------------------------------------------------------- 1 | getSectionParent($current)) { 16 | return []; 17 | } 18 | 19 | return Blink::once($this->getCacheKey($parent), function () use ($parent) { 20 | return $parent->cascade('seo'); 21 | }); 22 | } 23 | 24 | public function getAugmentedSectionDefaults($current) 25 | { 26 | if (! $parent = $this->getSectionParent($current)) { 27 | return []; 28 | } 29 | 30 | return Blink::once($this->getCacheKey($parent).'.augmented', function () use ($parent) { 31 | return Blueprint::make() 32 | ->setContents([ 33 | 'fields' => Fields::new()->getConfig(), 34 | ]) 35 | ->fields() 36 | ->addValues($seo = $parent->cascade('seo') ?: []) 37 | ->augment() 38 | ->values() 39 | ->only(array_keys($seo)); 40 | }); 41 | } 42 | 43 | protected function getCacheKey($parent) 44 | { 45 | return 'seo-pro.section-defaults.'.get_class($parent).'::'.$parent->handle(); 46 | } 47 | 48 | protected function getSectionParent($current) 49 | { 50 | if ($current instanceof Entry) { 51 | return $current->collection(); 52 | } elseif ($current instanceof Term || $current instanceof LocalizedTerm) { 53 | return $current->taxonomy(); 54 | } 55 | 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/GraphQL/AlternateLocaleType.php: -------------------------------------------------------------------------------- 1 | self::NAME, 14 | ]; 15 | 16 | public function fields(): array 17 | { 18 | return [ 19 | 'site' => [ 20 | 'type' => GraphQL::nonNull(GraphQL::type(SiteType::NAME)), 21 | ], 22 | 'url' => [ 23 | 'type' => GraphQL::nonNull(GraphQL::string()), 24 | ], 25 | ]; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/GraphQL/SeoProType.php: -------------------------------------------------------------------------------- 1 | self::NAME, 19 | ]; 20 | 21 | public function fields(): array 22 | { 23 | return [ 24 | 'site_name' => [ 25 | 'type' => GraphQL::string(), 26 | ], 27 | 'site_name_position' => [ 28 | 'type' => GraphQL::string(), 29 | ], 30 | 'site_name_separator' => [ 31 | 'type' => GraphQL::string(), 32 | ], 33 | 'title' => [ 34 | 'type' => GraphQL::string(), 35 | ], 36 | 'description' => [ 37 | 'type' => GraphQL::string(), 38 | ], 39 | 'priority' => [ 40 | 'type' => GraphQL::float(), 41 | 'resolve' => function ($meta) { 42 | return (float) $meta['priority']->value(); 43 | }, 44 | ], 45 | 'change_frequency' => [ 46 | 'type' => GraphQL::string(), 47 | ], 48 | 'compiled_title' => [ 49 | 'type' => GraphQL::string(), 50 | ], 51 | 'og_title' => [ 52 | 'type' => GraphQL::string(), 53 | ], 54 | 'canonical_url' => [ 55 | 'type' => GraphQL::string(), 56 | ], 57 | 'prev_url' => [ 58 | 'type' => GraphQL::string(), 59 | ], 60 | 'next_url' => [ 61 | 'type' => GraphQL::string(), 62 | ], 63 | 'home_url' => [ 64 | 'type' => GraphQL::string(), 65 | ], 66 | 'humans_txt' => [ 67 | 'type' => GraphQL::string(), 68 | ], 69 | 'site' => [ 70 | 'type' => GraphQL::type(SiteType::NAME), 71 | ], 72 | 'alternate_locales' => [ 73 | 'type' => GraphQL::listOf(GraphQL::type(AlternateLocaleType::NAME)), 74 | ], 75 | 'last_modified' => (new DateField)->setValueResolver(function ($meta) { 76 | return $meta['last_modified']; 77 | }), 78 | 'twitter_card' => [ 79 | 'type' => GraphQL::string(), 80 | ], 81 | 'twitter_handle' => [ 82 | 'type' => GraphQL::string(), 83 | ], 84 | 'image' => [ 85 | 'type' => GraphQL::type('AssetInterface'), 86 | 'resolve' => function ($meta) { 87 | return optional($meta['image'] ?? null)->value(); 88 | }, 89 | ], 90 | 'html' => [ 91 | 'type' => GraphQL::string(), 92 | 'resolve' => function ($meta) { 93 | return $this->renderMetaHtml($meta); 94 | }, 95 | ], 96 | ]; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/HasAssetField.php: -------------------------------------------------------------------------------- 1 | 'assets', 20 | 'container' => $container, 21 | 'max_files' => 1, 22 | ]; 23 | } 24 | 25 | /** 26 | * Show helpful asset field config error. 27 | * 28 | * @return array 29 | */ 30 | protected static function getAssetFieldContainerError() 31 | { 32 | return [ 33 | 'type' => 'html', 34 | 'html' => <<<'HTML' 35 |
36 | Asset container not configured. 37 | 38 | Learn more 39 | 40 |
41 | HTML, 42 | ]; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Http/Controllers/CollectionDefaultsController.php: -------------------------------------------------------------------------------- 1 | with(SiteDefaults::load()->all()) 17 | ->get(); 18 | 19 | $contents = view('seo-pro::humans', $cascade); 20 | 21 | $response = response() 22 | ->make($contents) 23 | ->header('Content-Type', 'text/plain'); 24 | 25 | return $response; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Http/Controllers/ReportController.php: -------------------------------------------------------------------------------- 1 | can('view seo reports'), 403); 15 | 16 | $reports = Report::all(); 17 | 18 | return $reports->isNotEmpty() 19 | ? view('seo-pro::reports.index', ['reports' => $reports]) 20 | : view('seo-pro::reports.create'); 21 | } 22 | 23 | public function create(Request $request) 24 | { 25 | abort_unless(User::current()->can('view seo reports'), 403); 26 | 27 | $report = Report::create()->save(); 28 | 29 | return redirect()->cpRoute('seo-pro.reports.show', $report->id()); 30 | } 31 | 32 | public function show(Request $request, $id) 33 | { 34 | abort_unless(User::current()->can('view seo reports'), 403); 35 | 36 | abort_unless($report = Report::find($id), 404); 37 | 38 | return view('seo-pro::reports.show', ['report' => $report]); 39 | } 40 | 41 | public function destroy($id) 42 | { 43 | abort_unless(User::current()->can('delete seo reports'), 403); 44 | 45 | return Report::find($id)->delete(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/Http/Controllers/ReportPagesController.php: -------------------------------------------------------------------------------- 1 | can('view seo reports'), 403); 17 | 18 | $data = Report::find($id)->data(); 19 | 20 | // If report is still generating, 21 | // we'll get a report instance with a status for the front end to poll against. 22 | // When it's finished generating, `data()` will return a collection. 23 | if ($data instanceof Report) { 24 | return $data; 25 | } 26 | 27 | $data['columns'] = [ 28 | Column::make('status')->label(__('Status')), 29 | Column::make('url')->label(__('URL')), 30 | Column::make('actionable')->label(__('Actionable'))->sortable(false), 31 | ]; 32 | 33 | $data['sortColumn'] = $request->input('sortColumn', 'status'); 34 | $data['sortDirection'] = $request->input('sortDirection', 'asc'); 35 | 36 | $pages = $data['pages'] 37 | ->sortBy( 38 | callback: fn ($value) => $this->sortablePageValue($value, $data['sortColumn']), 39 | descending: $data['sortDirection'] === 'desc', 40 | ) 41 | ->values(); 42 | 43 | $currentPage = $request->input('page', 1); 44 | $perPage = $request->input('perPage', config('statamic.cp.pagination_size')); 45 | 46 | $data['pages'] = new LengthAwarePaginator( 47 | $pages->forPage($currentPage, $perPage)->values(), 48 | $pages->count(), 49 | $perPage, 50 | $currentPage, 51 | ); 52 | 53 | return $data; 54 | } 55 | 56 | private function sortablePageValue($value, $column) 57 | { 58 | $value = $value[$column]; 59 | 60 | if ($column !== 'status') { 61 | return $value; 62 | } 63 | 64 | if ($value === 'fail') { 65 | return '1fail'; 66 | } elseif ($value === 'warning') { 67 | return '2warning'; 68 | } elseif ($value === 'pass') { 69 | return '3pass'; 70 | } 71 | 72 | return $value; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/Http/Controllers/SiteDefaultsController.php: -------------------------------------------------------------------------------- 1 | can('edit seo site defaults'), 403); 16 | 17 | $siteDefaults = SiteDefaults::load(); 18 | 19 | $blueprint = $siteDefaults->blueprint(); 20 | 21 | $fields = $blueprint 22 | ->fields() 23 | ->addValues($siteDefaults->all()) 24 | ->preProcess(); 25 | 26 | return view('seo-pro::edit', [ 27 | 'title' => __('seo-pro::messages.site_defaults'), 28 | 'action' => cp_route('seo-pro.site-defaults.update'), 29 | 'blueprint' => $blueprint->toPublishArray(), 30 | 'meta' => $fields->meta(), 31 | 'values' => $fields->values(), 32 | ]); 33 | } 34 | 35 | public function update(Request $request) 36 | { 37 | abort_unless(User::current()->can('edit seo site defaults'), 403); 38 | 39 | $blueprint = SiteDefaults::load()->blueprint(); 40 | 41 | $fields = $blueprint->fields()->addValues($request->all()); 42 | 43 | $fields->validate(); 44 | 45 | $values = Arr::removeNullValues($fields->process()->values()->all()); 46 | 47 | SiteDefaults::load($values)->save(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/Http/Controllers/SitemapController.php: -------------------------------------------------------------------------------- 1 | addMinutes(config('statamic.seo-pro.sitemap.expire')); 17 | 18 | if (config('statamic.seo-pro.sitemap.pagination.enabled', false)) { 19 | $content = Cache::remember(Sitemap::CACHE_KEY.'_index', $cacheUntil, function () { 20 | return view('seo-pro::sitemap_index', [ 21 | 'xml_header' => '', 22 | 'sitemaps' => app(Sitemap::class)->paginatedSitemaps(), 23 | ])->render(); 24 | }); 25 | } else { 26 | $content = Cache::remember(Sitemap::CACHE_KEY, $cacheUntil, function () { 27 | return view('seo-pro::sitemap', [ 28 | 'xml_header' => '', 29 | 'pages' => app(Sitemap::class)->pages(), 30 | ])->render(); 31 | }); 32 | } 33 | 34 | return response($content)->header('Content-Type', 'text/xml'); 35 | } 36 | 37 | public function show($page) 38 | { 39 | abort_unless(config('statamic.seo-pro.sitemap.enabled'), 404); 40 | abort_unless(config('statamic.seo-pro.sitemap.pagination.enabled'), 404); 41 | abort_unless(filter_var($page, FILTER_VALIDATE_INT), 404); 42 | 43 | $cacheUntil = Carbon::now()->addMinutes(config('statamic.seo-pro.sitemap.expire')); 44 | 45 | $cacheKey = Sitemap::CACHE_KEY.'_'.$page; 46 | 47 | $content = Cache::remember($cacheKey, $cacheUntil, function () use ($page) { 48 | abort_if(empty($pages = app(Sitemap::class)->paginatedPages($page)), 404); 49 | 50 | return view('seo-pro::sitemap', [ 51 | 'xml_header' => '', 52 | 'pages' => $pages, 53 | ])->render(); 54 | }); 55 | 56 | return response($content)->header('Content-Type', 'text/xml'); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Http/Controllers/TaxonomyDefaultsController.php: -------------------------------------------------------------------------------- 1 | render(); 18 | 19 | // Remove new lines. 20 | $html = str_replace(["\n", "\r"], '', $html); 21 | 22 | // Remove whitespace between elements. 23 | $html = preg_replace('/(>)\s*(<)/', '$1$2', $html); 24 | 25 | // Add cleaner line breaks. 26 | if ($withLineBreaks) { 27 | $html = preg_replace('/(<[^\/])/', "\n$1", $html); 28 | } 29 | 30 | return trim($html); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/Reporting/Chunk.php: -------------------------------------------------------------------------------- 1 | id = $id; 24 | $this->contentIds = $contentIds; 25 | $this->report = $report; 26 | } 27 | 28 | protected function folderPath() 29 | { 30 | return $this->report->chunksFolder()."/{$this->id}"; 31 | } 32 | 33 | protected function yamlPath() 34 | { 35 | return $this->folderPath().'/chunk.yaml'; 36 | } 37 | 38 | public function save() 39 | { 40 | File::put($this->yamlPath(), YAML::dump([ 41 | 'ids' => $this->contentIds, 42 | ])); 43 | 44 | return $this; 45 | } 46 | 47 | public function queueGenerate() 48 | { 49 | $ids = $this->contentIds; 50 | 51 | dispatch(function () use ($ids) { 52 | $this->generate($ids); 53 | }); 54 | } 55 | 56 | protected function generate($ids) 57 | { 58 | $content = Cache::get($this->report->cacheKey(Report::CONTENT_CACHE_KEY_SUFFIX)); 59 | 60 | foreach ($ids as $id) { 61 | $this->createPage($content[$id] ?? Data::find($id))?->save(); 62 | } 63 | 64 | File::delete($this->folderPath()); 65 | 66 | if ($this->wasLastChunk()) { 67 | $this->report->finalize(); 68 | } 69 | } 70 | 71 | protected function wasLastChunk() 72 | { 73 | return File::getFolders($this->report->chunksFolder())->isEmpty(); 74 | } 75 | 76 | protected function createPage($content) 77 | { 78 | if ($content->value('seo') === false || is_null($content->uri())) { 79 | return; 80 | } 81 | 82 | $data = (new Cascade) 83 | ->with(SiteDefaults::load()->augmented()) 84 | ->with($this->getAugmentedSectionDefaults($content)) 85 | ->with($content->augmentedValue('seo')->value()) 86 | ->withCurrent($content) 87 | ->get(); 88 | 89 | return new Page($content->id(), $data, $this->report); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/Reporting/Rules/Concerns/FailsWhenPagesDontPass.php: -------------------------------------------------------------------------------- 1 | failures = $this->report->pages()->filter(function ($page) { 14 | return ! $this->passesPageRule($page); 15 | })->count(); 16 | } 17 | 18 | protected function passesPageRule(Page $page) 19 | { 20 | $rule = new static; 21 | 22 | $rule 23 | ->setPage($page) 24 | ->setReport($this->report) 25 | ->load($page->results()[$this->id()]); 26 | 27 | return $rule->status() === 'pass'; 28 | } 29 | 30 | public function saveSite() 31 | { 32 | return $this->failures; 33 | } 34 | 35 | public function loadSite($data) 36 | { 37 | $this->failures = $data; 38 | } 39 | 40 | public function siteStatus() 41 | { 42 | return $this->failures === 0 ? 'pass' : 'fail'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Reporting/Rules/Concerns/WarnsWhenPagesDontPass.php: -------------------------------------------------------------------------------- 1 | failures === 0 ? 'pass' : 'warning'; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/Reporting/Rules/NoUnderscoresInUrl.php: -------------------------------------------------------------------------------- 1 | failures, 34 | ['count' => $this->failures] 35 | ); 36 | } 37 | 38 | public function processPage() 39 | { 40 | $this->passes = ! Str::contains($this->page->url(), '_'); 41 | } 42 | 43 | public function pageStatus() 44 | { 45 | return $this->passes ? 'pass' : 'fail'; 46 | } 47 | 48 | public function savePage() 49 | { 50 | return $this->passes; 51 | } 52 | 53 | public function loadPage($data) 54 | { 55 | $this->passes = $data; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Reporting/Rules/SiteName.php: -------------------------------------------------------------------------------- 1 | passes = ! empty(trim($this->siteName())); 20 | } 21 | 22 | public function status() 23 | { 24 | return $this->passes ? 'pass' : 'fail'; 25 | } 26 | 27 | public function save() 28 | { 29 | return $this->passes; 30 | } 31 | 32 | public function load($data) 33 | { 34 | $this->passes = $data; 35 | } 36 | 37 | public function comment() 38 | { 39 | return $this->siteName(); 40 | } 41 | 42 | protected function siteName() 43 | { 44 | return $this->report->defaults()->get('site_name'); 45 | } 46 | 47 | public function maxPoints() 48 | { 49 | return 10; 50 | } 51 | 52 | public function demerits() 53 | { 54 | if (! $this->passes) { 55 | return $this->maxPoints(); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Reporting/Rules/ThreeSegmentUrls.php: -------------------------------------------------------------------------------- 1 | failures, 33 | ['count' => $this->failures] 34 | ); 35 | } 36 | 37 | public function processPage() 38 | { 39 | $url = parse_url($this->page->url())['path'] ?? '/'; 40 | $this->slashes = substr_count($url, '/'); 41 | } 42 | 43 | public function pageStatus() 44 | { 45 | return $this->slashes <= 3 ? 'pass' : 'warning'; 46 | } 47 | 48 | public function siteStatus() 49 | { 50 | return $this->failures === 0 ? 'pass' : 'warning'; 51 | } 52 | 53 | public function savePage() 54 | { 55 | return $this->slashes; 56 | } 57 | 58 | public function loadPage($data) 59 | { 60 | $this->slashes = $data; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/Reporting/Rules/UniqueMetaDescription.php: -------------------------------------------------------------------------------- 1 | $this->failures]); 35 | } 36 | 37 | public function pageFailingComment() 38 | { 39 | return __('seo-pro::messages.rules.unique_description_page_failing', [ 40 | 'count' => $this->count, 41 | 'description' => $this->metaDescription(), 42 | ]); 43 | } 44 | 45 | public function pagePassingComment() 46 | { 47 | return $this->metaDescription(); 48 | } 49 | 50 | public function processPage() 51 | { 52 | $this->count = $this 53 | ->groupAllPagesByDescription() 54 | ->get($this->metaDescription()) 55 | ->count(); 56 | } 57 | 58 | protected function groupAllPagesByDescription() 59 | { 60 | return Blink::once('seo-pro-report-'.$this->report->id().'-page-descriptions-grouped', function () { 61 | return $this->page->report()->pages()->mapToGroups(function ($page) { 62 | return [$page->get('description') => $page->id()]; 63 | }); 64 | }); 65 | } 66 | 67 | public function savePage() 68 | { 69 | return $this->count; 70 | } 71 | 72 | public function loadPage($data) 73 | { 74 | $this->count = $data; 75 | } 76 | 77 | public function pageStatus() 78 | { 79 | return $this->count === 1 ? 'pass' : 'fail'; 80 | } 81 | 82 | protected function metaDescription() 83 | { 84 | return $this->page->get('description'); 85 | } 86 | 87 | public function maxPoints() 88 | { 89 | return $this->points() * $this->report->pages()->count(); 90 | } 91 | 92 | public function demerits() 93 | { 94 | return $this->points() * $this->failures; 95 | } 96 | 97 | protected function points() 98 | { 99 | return 1; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Reporting/Rules/UniqueTitleTag.php: -------------------------------------------------------------------------------- 1 | $this->failures]); 35 | } 36 | 37 | public function pageFailingComment() 38 | { 39 | return __('seo-pro::messages.rules.unique_title_page_failing', [ 40 | 'count' => $this->count, 41 | 'title' => $this->title(), 42 | ]); 43 | } 44 | 45 | public function pagePassingComment() 46 | { 47 | return $this->title(); 48 | } 49 | 50 | public function processPage() 51 | { 52 | $this->count = $this 53 | ->groupAllPagesByTitle() 54 | ->get($this->title()) 55 | ->count(); 56 | } 57 | 58 | protected function groupAllPagesByTitle() 59 | { 60 | return Blink::once('seo-pro-report-'.$this->report->id().'-page-titles-grouped', function () { 61 | return $this->page->report()->pages()->mapToGroups(function ($page) { 62 | return [$page->get('title') => $page->id()]; 63 | }); 64 | }); 65 | } 66 | 67 | public function savePage() 68 | { 69 | return $this->count; 70 | } 71 | 72 | public function loadPage($data) 73 | { 74 | $this->count = $data; 75 | } 76 | 77 | public function pageStatus() 78 | { 79 | return $this->count === 1 ? 'pass' : 'fail'; 80 | } 81 | 82 | protected function title() 83 | { 84 | return $this->page->get('title'); 85 | } 86 | 87 | public function maxPoints() 88 | { 89 | return $this->points() * $this->report->pages()->count(); 90 | } 91 | 92 | public function demerits() 93 | { 94 | return $this->points() * $this->failures; 95 | } 96 | 97 | protected function points() 98 | { 99 | return 2; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/Sitemap/Page.php: -------------------------------------------------------------------------------- 1 | data = collect($data); 12 | 13 | return $this; 14 | } 15 | 16 | public function path() 17 | { 18 | return parse_url($this->loc())['path'] ?? '/'; 19 | } 20 | 21 | public function loc() 22 | { 23 | return $this->data->get('canonical_url'); 24 | } 25 | 26 | public function lastmod() 27 | { 28 | return $this->data->get('last_modified')->format('Y-m-d'); 29 | } 30 | 31 | public function changefreq() 32 | { 33 | return $this->data->get('change_frequency'); 34 | } 35 | 36 | public function priority() 37 | { 38 | return $this->data->get('priority'); 39 | } 40 | 41 | public function toArray() 42 | { 43 | return [ 44 | 'path' => $this->path(), 45 | 'loc' => $this->loc(), 46 | 'lastmod' => $this->lastmod(), 47 | 'changefreq' => $this->changefreq(), 48 | 'priority' => $this->priority(), 49 | ]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Subscriber.php: -------------------------------------------------------------------------------- 1 | 'ensureSeoFields', 21 | Events\TermBlueprintFound::class => 'ensureSeoFields', 22 | Events\CollectionSaved::class => 'clearSitemapCache', 23 | Events\EntrySaved::class => 'clearSitemapCache', 24 | Events\TaxonomySaved::class => 'clearSitemapCache', 25 | Events\TermSaved::class => 'clearSitemapCache', 26 | ]; 27 | 28 | /** 29 | * Register the listeners for the subscriber. 30 | * 31 | * @param \Illuminate\Events\Dispatcher $events 32 | */ 33 | public function subscribe($events) 34 | { 35 | foreach ($this->events as $event => $method) { 36 | $events->listen($event, self::class.'@'.$method); 37 | } 38 | } 39 | 40 | /** 41 | * Ensure section blueprint has (or doesn't have) SEO fields. 42 | * 43 | * @param mixed $event 44 | */ 45 | public function ensureSeoFields($event) 46 | { 47 | Blueprint::on($event)->ensureSeoFields( 48 | $this->seoIsEnabledForSection($event) 49 | ); 50 | } 51 | 52 | /** 53 | * Clear sitemap cache. 54 | */ 55 | public function clearSitemapCache() 56 | { 57 | Cache::forget(Sitemap::CACHE_KEY); 58 | } 59 | 60 | /** 61 | * Check if SEO is enabled for section. 62 | * 63 | * @param mixed $event 64 | * @return bool 65 | */ 66 | protected function seoIsEnabledForSection($event) 67 | { 68 | $namespace = $event->blueprint->namespace(); 69 | 70 | if (Str::startsWith($namespace, 'collections.')) { 71 | $section = Collection::findByHandle(Str::after($namespace, 'collections.')); 72 | } elseif (Str::startsWith($namespace, 'taxonomies.')) { 73 | $section = Taxonomy::findByHandle(Str::after($namespace, 'taxonomies.')); 74 | } else { 75 | throw new \Exception('Unknown section type.'); 76 | } 77 | 78 | return $section->cascade('seo') !== false; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/Tags/SeoProTags.php: -------------------------------------------------------------------------------- 1 | context->value('seo') === false) { 26 | return; 27 | } 28 | 29 | return $this->renderMetaHtml($this->metaData(), true); 30 | } 31 | 32 | /** 33 | * The {{ seo_pro:meta_data }} tag. 34 | * 35 | * @return string 36 | */ 37 | public function metaData() 38 | { 39 | $current = optional($this->context->get('seo'))->augmentable(); 40 | 41 | $metaData = (new Cascade) 42 | ->with(SiteDefaults::load()->augmented()) 43 | ->with($this->getAugmentedSectionDefaults($current)) 44 | ->with($this->context->value('seo')) 45 | ->with($current ? [] : $this->context->except('template_content')) 46 | ->withCurrent($current) 47 | ->get(); 48 | 49 | $metaData['is_twitter_glide_enabled'] = $this->isGlidePresetEnabled('seo_pro_twitter'); 50 | $metaData['is_og_glide_enabled'] = $this->isGlidePresetEnabled('seo_pro_og'); 51 | 52 | return $this->aliasedResult($metaData); 53 | } 54 | 55 | /** 56 | * The {{ seo_pro:dump_meta_data }} tag. 57 | * 58 | * @return string 59 | */ 60 | public function dumpMetaData() 61 | { 62 | return dd($this->metaData()); 63 | } 64 | 65 | /** 66 | * Check if glide preset is enabled. 67 | * 68 | * @param string $preset 69 | * @return bool 70 | */ 71 | protected function isGlidePresetEnabled($preset) 72 | { 73 | $server = app(\League\Glide\Server::class); 74 | 75 | return collect($server->getPresets())->has($preset); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/Widgets/SeoProWidget.php: -------------------------------------------------------------------------------- 1 | Report::latest(), 14 | ]); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/assets/img/coffee-mug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site-localized/assets/img/coffee-mug.jpg -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/assets/img/stetson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site-localized/assets/img/stetson.jpg -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Cloud Filesystem Disk 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Many applications store files both locally and in the cloud. For this 24 | | reason, you may specify a default "cloud" driver here. This driver 25 | | will be bound as the Cloud disk implementation in the container. 26 | | 27 | */ 28 | 29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Filesystem Disks 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may configure as many filesystem "disks" as you wish, and you 37 | | may even configure multiple disks of the same driver. Defaults have 38 | | been setup for each driver as an example of the required options. 39 | | 40 | | Supported Drivers: "local", "ftp", "s3", "rackspace" 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'public' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/public'), 54 | 'url' => env('APP_URL').'/storage', 55 | 'visibility' => 'public', 56 | ], 57 | 58 | 's3' => [ 59 | 'driver' => 's3', 60 | 'key' => env('AWS_ACCESS_KEY_ID'), 61 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 62 | 'region' => env('AWS_DEFAULT_REGION'), 63 | 'bucket' => env('AWS_BUCKET'), 64 | 'url' => env('AWS_URL'), 65 | ], 66 | 67 | 'assets' => [ 68 | 'driver' => 'local', 69 | 'root' => base_path('assets'), 70 | 'url' => '/assets', 71 | 'visibility' => 'public', 72 | ], 73 | 74 | ], 75 | 76 | ]; 77 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/config/statamic/stache.php: -------------------------------------------------------------------------------- 1 | true, 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may configure which stores are used inside the Stache. 26 | | 27 | */ 28 | 29 | 'stores' => [ 30 | 31 | 'taxonomies' => [ 32 | 'class' => Stores\TaxonomiesStore::class, 33 | 'directory' => base_path('content/taxonomies'), 34 | ], 35 | 36 | 'terms' => [ 37 | 'class' => Stores\TermsStore::class, 38 | 'directory' => base_path('content/taxonomies'), 39 | ], 40 | 41 | 'collections' => [ 42 | 'class' => Stores\CollectionsStore::class, 43 | 'directory' => base_path('content/collections'), 44 | ], 45 | 46 | 'entries' => [ 47 | 'class' => Stores\EntriesStore::class, 48 | 'directory' => base_path('content/collections'), 49 | ], 50 | 51 | 'navigation' => [ 52 | 'class' => Stores\NavigationStore::class, 53 | 'directory' => base_path('content/navigation'), 54 | ], 55 | 56 | 'globals' => [ 57 | 'class' => Stores\GlobalsStore::class, 58 | 'directory' => base_path('content/globals'), 59 | ], 60 | 61 | 'asset-containers' => [ 62 | 'class' => Stores\AssetContainersStore::class, 63 | 'directory' => base_path('content/assets'), 64 | ], 65 | 66 | 'users' => [ 67 | 'class' => Stores\UsersStore::class, 68 | 'directory' => base_path('users'), 69 | ], 70 | 71 | ], 72 | 73 | /* 74 | |-------------------------------------------------------------------------- 75 | | Indexes 76 | |-------------------------------------------------------------------------- 77 | | 78 | | Here you may define any additional indexes that will be inherited 79 | | by each store in the Stache. You may also define indexes on a 80 | | per-store level by adding an "indexes" key to its config. 81 | | 82 | */ 83 | 84 | 'indexes' => [ 85 | // 86 | ], 87 | 88 | ]; 89 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/config/statamic/users.php: -------------------------------------------------------------------------------- 1 | 'file', 19 | 20 | 'repositories' => [ 21 | 22 | 'file' => [ 23 | 'driver' => 'file', 24 | 'paths' => [ 25 | 'users' => base_path('users'), 26 | 'roles' => resource_path('users/roles.yaml'), 27 | 'groups' => resource_path('users/groups.yaml'), 28 | ], 29 | ], 30 | 31 | 'eloquent' => [ 32 | 'driver' => 'eloquent', 33 | ], 34 | 35 | ], 36 | 37 | /* 38 | |-------------------------------------------------------------------------- 39 | | Avatars 40 | |-------------------------------------------------------------------------- 41 | | 42 | | User avatars are initials by default, with custom options for services 43 | | like Gravatar.com. 44 | | 45 | | Supported: "initials", "gravatar", or a custom class name. 46 | | 47 | */ 48 | 49 | 'avatars' => 'initials', 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | New User Roles 54 | |-------------------------------------------------------------------------- 55 | | 56 | | When registering new users through the user:register_form tag, these 57 | | roles will automatically be applied to your newly created users. 58 | | 59 | */ 60 | 61 | 'new_user_roles' => [ 62 | // 63 | ], 64 | 65 | /* 66 | |-------------------------------------------------------------------------- 67 | | Password Brokers 68 | |-------------------------------------------------------------------------- 69 | | 70 | | When resetting passwords, Statamic uses an appropriate password broker. 71 | | Here you may define which broker should be used for each situation. 72 | | You may want a longer expiry for user activations, for example. 73 | | 74 | */ 75 | 76 | 'passwords' => [ 77 | 'resets' => config('auth.defaults.passwords'), 78 | 'activations' => config('auth.defaults.passwords'), 79 | ], 80 | 81 | ]; 82 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site-localized/content/assets/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/assets/assets.yaml: -------------------------------------------------------------------------------- 1 | title: Assets 2 | disk: assets -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site-localized/content/collections/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/articles.yaml: -------------------------------------------------------------------------------- 1 | title: Articles 2 | sites: 3 | - default 4 | - french 5 | template: articles.show 6 | mount: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63 7 | taxonomies: 8 | - topics 9 | revisions: false 10 | route: '{slug}' 11 | date: true 12 | date_behavior: 13 | past: public 14 | future: private 15 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/articles/default/1994-07-05.magic.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'The Magic Happens at 7 1/2 Pumps' 3 | topics: 4 | - sneakers 5 | excerpt: 'It took me 2 years, 1 month, and 21 days to save up for a pair of Reebok Pumps. When I finally got them, they didn''t work as advertised. Or did they?' 6 | id: af43e0fb-a338-4433-b60a-3bed773be341 7 | --- 8 | Ever since the day Dee Brown pumped up his Reeboks and went on to win the 1991 NBA Slam Dunk Contest, I had been saving to buy a pair. 9 | 10 | It took me 2 years, 1 month, and 21 days, but I'm a proud owner of those black, white, and orange Reebok Pump Omni Lights. 11 | 12 | ![Reebok Pump Omni Lights](/assets/content/reebok-pumps.jpg) 13 | 14 | Only, they didn't work as advertised. The commercials promised that with just a few pumps and I'd soar like Jordan, like an eagle, like a feather on the wind. In reality, I lost 2mm on my vertical jump because they're heavier than my previous kicks. I was devastated, but determined. 15 | 16 | I hunted down a [VHS tape](https://www.youtube.com/watch?v=6uD8ZqkoM5E) of the dunk contest and watched it a dozen times. It was undeniable! Dee Brown lined up for a dunk bit first paused to reach down, pump his Reeboks, and immediately dazzled the crowd. This was no fluke. It was the shoes. I studied the footage. Closely, carefully, and methodically. 17 | 18 | At first it appeared that Dee pumped his sneakers 10 or 11 times. He really went to town on those things. But neither 10 pumps nor 11 pumps made any difference for me. In fact, 11 pumps started to cut off my circulation which one time caused me to stumble and fall into a chain link fence which left diamond shape marks on my face for the better part of a day. 19 | 20 | So I went full scientific method. In order, I tried: 21 | 22 | - 8 pumps 3 times 23 | - 9 pumps 3 times 24 | - 10 pumps 5 times 25 | - 11 pumps 5 times 26 | - 12 pumps once, even though 11 was already too many 27 | 28 | **Nothing.** Shame. Regret. I had spent almost 2 years of allowance on these sneakers! But then I noticed something. I was reviewing Dee's footage and even though the VHS tape was worn and tracking poorly from all the use, I saw it. 3 missed pumps and one single half pump. It's not clear if his fingers were sweaty and he mis-pumped a few times or perhaps he was masking the secret to his greatness. Either way, the secret knowledge was mine, and just time too because my VHS tape was worn thin and nearly unplayable. 29 | 30 | **The magic happens at 7 1/2 pumps.** 31 | 32 | With Dee and Reebok's secret knowledge in hand, I could dunk! I could soar! I began playing street ball downtown for money, and started to rake it in. I made friends more easily than any point in my life and enemies even easilier. I found I, just like Dee Brown, had to mask the number of pumps lest my competitors gain the hard-earned secret to my success. 33 | 34 | > “Where'd you learn how to jump like that, kid?” 35 | 36 | I spun around to see NBA legend Clyde Drexler towering over me. I had just schooled a trio of posers in a rousing game of 3-on-1 and had literally dunked over two of them at once. 37 | 38 | "Oh you know, here and there." I replied. He eyed my pumps. I eyed his pumps. We made eye content and something of a shared secret passed between us. The corner of his mouth cracked upwards in a smirk. "I expect I'll be seeing you in a few years, kid." 39 | 40 | I expect he shall. I expect very much indeed. 41 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/articles/default/1996-08-16.nectar.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Nectar of the Gods' 3 | topics: 4 | - soda 5 | excerpt: 'The time had come. We had seen the commercials. This was our first foray into the underground competitive world of Surge.' 6 | id: 8e4b4e60-5dfb-47b0-a2d7-a904d64aeb80 7 | --- 8 | The day started just like any other. Wake up at 5:30am, brush my teeth, bathe in a tub of warm milk, and trim my toenails while quietly resenting the fact that _Flipper_ was on Nickelodeon at this hour instead of _Rocko's Modern Life_. That would have to wait until 5:30*pm* for that, and I am impatient. 9 | 10 | In truth, the day would likely be spent slogging my way through _Gumby_, _Rugrats_, _Muppet Babies_, _Allegra's Window_, _Gullah Gullah Island_, _Eureeka's Castle_, and numerous other shows fit for my little sister before I could hang with Rocko. But I digress. My life was about to change. 11 | 12 | The doorbell rang. It was 11am and I opened the door to see my friend Matt standing there with a maniacal grin on his face. Behind him, toppled furniture was scattered about my yard and a dozen neighborhood kids were arranged in a haphazard circle. In the center of this ring of humans stood a tall pedestal upon which rested a cylindrical and metallic green can. 13 | 14 | The time had come. We had seen the commercials. This was our first foray into the [underground competitive world](https://www.youtube.com/watch?v=CTY8hrvFck8) of Fully Loaded Citrus Sodas with Carbos. 15 | 16 | **Off to the side someone screamed the single word that would forever alter the course my life.** 17 | 18 | > “Surge!!!” 19 | 20 | As if bolt of lightning struck us all at once, we sprinted — nay, _hurled_ our bodies towards the pedestal without regard for life or limb. The collision of human bodies could be heard 6 blocks away as fists swung and hands clawed, hair tore away in chunks, buttons flew from plaid hoodies tied around waists, and sneakers took to the air, loose of their foots. 21 | 22 | I can't say how, or at what cost, but my hand closed around the ice cold can first. It was mine. The crowd fell back, subservient to the victor like the days of Sparticus, Crixus, and Marcus Attilius. I cracked the tab and a cool spray of citrus coated those lucky enough to be close. I tossed my head back and from the height of my upwards and outstretched arm, poured the sweet nectar of the gods down my throat. 23 | 24 | ![Surge](/assets/content/surge.jpg) 25 | 26 | ## Wherein I left my body 27 | 28 | I could hear a symphony from on high, replete with horns, trumpets, harps, and one very faint ukulele. My soul lifted up out of me and I was carried away in a torrent of joy. I looked down and for a brief moment I could see my body before a wave of carbo-laden sucrose crashed over my consciousness. 29 | 30 | I lost all sense of time. Did I surf the seas of maltodextrin for a minute? An hour? A year? Was Yellow #5 my brother? Truly I could not tell you, for I do not know. 31 | 32 | ## Wherein I returned 33 | 34 | My body was transformed. Lean muscle rippled with unbridled strength and my vision had become sharp and keen. My mind raced with access to deep wells of new knowledge and wisdom. I surveyed my lawn, the neighborhood, and my subordinates and knew my life would never be the same. 35 | 36 | **Victory is sweet. Surge is sweeter.** 37 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/articles/default/1996-11-18.dance.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: '''Dance Like No One is Watching'' Is Bad Advice' 3 | topics: 4 | - dance 5 | excerpt: 'The Macarena is an international hit & dance craze. The song is inspired by flamenco dancer Diana Herrera''s beauty, but do you know where the dance came from?' 6 | id: 7ac0bdda-1b84-45f8-ac52-2575dd7e8251 7 | --- 8 | The Macarena by Los Del Rio (Remixed by the Bayside Boys) has been #1 on the charts for 14 weeks in a row. 9 | 10 | It's an international hit and dance craze. Rumor has it that the band spotted a beautiful flamenco dancer named Diana Patricia Cubillan Herrera at a private party held by the Venezuelan empresario in Venezuela. Her beauty and grace inspired them to write the song, and the rest is history. 11 | 12 | But do you know where the dance featured in their [music video](https://www.youtube.com/watch?v=MXVx6yJQbn8) (released earlier this year) came from? No, of course you don't. 13 | 14 | ## It happened in Rio 15 | 16 | Last spring I was vacationing in Rio with my family. We had been there a few weeks, staying in a friend of the family's villa in the quiet area of Lagoa. 17 | 18 | ![Lagoa](/assets/content/lagoa.jpg) 19 | 20 | My sisters were out kayaking on the lake just after sunrise one morning and I had just finished a bit of yoga on the roof to limber up. My mother always told me to dance like no one is watching, so I had grown accustom to practicing my soul moves without care for anyone passing by. 21 | 22 | I had just finished my series of self-healing moves focused on loving and hugging yourself when two older men in black suits waved up at me. 23 | 24 | > “Buenos movimientos, chico!” 25 | 26 | I waved back and shouted my thanks. They went on with their day, and I with mine and soon I forgot about the exchange. 27 | 28 | The next day they were back. And the next. On the fourth day they had a small crowd with them and a video camera – one of those fancy new handheld ones that used the little mini tapes. I wanted one of those. 29 | 30 | I finished my movements quickly and headed down the back stairs to meet these would-be fans. But when I rounded the corner they were gone. 31 | 32 | I didn't see them again after that. I asked around the neighborhood and discovered that they were a famous Spanish musical duo on an extended tour through South America. 33 | 34 | Imagine my surprise when the Macarena dance took the world by storm. I don't begrudge the world my moves – they have such meaning packed into them and everyone with an open mind can learn their lessons – but I never got so much as a thank you, nor did I earn a dime. 35 | 36 | ## The worst part 37 | 38 | The part of this story that bums me out the most, however, is that now when I dance my soul dance, people think I'm following a fad. Now I must be certain no one is watching when I dance. 39 | 40 | **Oh, how I've longed to share my story!** I thank you for listening. May you live long and dance your own dance without care or consequence. 41 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/articles/french/1996-08-16.nectar.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: d9848738-ca48-433e-b85f-8e9571780e0c 3 | origin: 8e4b4e60-5dfb-47b0-a2d7-a904d64aeb80 4 | blueprint: articles 5 | title: 'Les Nectar of the Gods' 6 | updated_by: 2769ab0f-b1d7-4acc-b6ab-725bd4a72643 7 | updated_at: 1632168024 8 | --- 9 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages.yaml: -------------------------------------------------------------------------------- 1 | title: Pages 2 | sites: 3 | - default 4 | - french 5 | - italian 6 | - british 7 | revisions: false 8 | route: '{parent_uri}/{slug}' 9 | structure: 10 | root: true 11 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/british/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: d1969705-fe5f-4b39-b99a-e93df3309695 3 | origin: home 4 | blueprint: pages 5 | updated_by: 2769ab0f-b1d7-4acc-b6ab-725bd4a72643 6 | updated_at: 1632166012 7 | --- 8 | I see a bonkers-ass bloke, with English Breakfast Tea! 9 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/default/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About 3 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 4 | updated_at: 1579284102 5 | template: page 6 | id: 62136fa2-9e5c-4c38-a894-a2753f02f5ff 7 | --- 8 | I'm just a kid living in the 90's, writing articles in his secret public journal wonder if someday, somewhere in the future, they will be read by someone. 9 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/default/articles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Articles 3 | template: page 4 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 5 | updated_at: 1579283552 6 | id: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63 7 | --- 8 | These are my various writings. Some might say they are cool. 9 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/default/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Home 3 | template: page 4 | subtitle: 'I see pride. I see power.' 5 | updated_by: b6c037ad-5bcc-41a8-a455-9ab54573f689 6 | updated_at: 1606223924 7 | id: home 8 | --- 9 | I see a bad-ass mother. 10 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/default/topics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Topics 3 | template: topics/index 4 | updated_by: ea0c21bd-9703-4bb1-9fed-58ec0e129dd7 5 | updated_at: 1579534416 6 | id: f5a53468-017e-4725-b5b6-a745df7e94cb 7 | --- 8 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/french/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 7d105969-e5ff-49b3-99ab-3d330f9695e9 3 | origin: 62136fa2-9e5c-4c38-a894-a2753f02f5ff 4 | blueprint: pages 5 | updated_by: 2769ab0f-b1d7-4acc-b6ab-725bd4a72643 6 | updated_at: 1632166012 7 | --- 8 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/french/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 3ea1f4aa-c9f2-4c5a-b7bc-e4ceed34dc87 3 | origin: home 4 | blueprint: pages 5 | updated_by: 2769ab0f-b1d7-4acc-b6ab-725bd4a72643 6 | updated_at: 1632166003 7 | --- 8 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/italian/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 9697d105-e5ff-49b3-99ab-f9695e93d330 3 | origin: 62136fa2-9e5c-4c38-a894-a2753f02f5ff 4 | blueprint: pages 5 | updated_by: 2769ab0f-b1d7-4acc-b6ab-725bd4a72643 6 | updated_at: 1632166012 7 | --- 8 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/collections/pages/italian/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: 4aa3ea1f-c9f2-4c5a-b7bc-d34dc87e4cee 3 | origin: home 4 | blueprint: pages 5 | updated_by: 2769ab0f-b1d7-4acc-b6ab-725bd4a72643 6 | updated_at: 1632166003 7 | --- 8 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/globals/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site-localized/content/globals/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/globals/default/settings.yaml: -------------------------------------------------------------------------------- 1 | site_name: 'Cool Writings' 2 | social: 3 | - 4 | name: Twitter 5 | url: 'https://twitter.com/jackmcdade' 6 | icon: site/social-icons/twitter.svg 7 | - 8 | name: Github 9 | url: 'https://github.com/statamic/starter-kit-cool-writings' 10 | icon: site/social-icons/github.svg 11 | - 12 | name: Email 13 | url: 'mailto:jack@statamic.com' 14 | icon: site/social-icons/email.svg 15 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/globals/french/settings.yaml: -------------------------------------------------------------------------------- 1 | origin: default 2 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/globals/settings.yaml: -------------------------------------------------------------------------------- 1 | title: Settings 2 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/navigation/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site-localized/content/navigation/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/taxonomies/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site-localized/content/taxonomies/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/taxonomies/topics.yaml: -------------------------------------------------------------------------------- 1 | title: Topics 2 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/taxonomies/topics/dance.yaml: -------------------------------------------------------------------------------- 1 | title: Dance 2 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 3 | updated_at: 1579284933 4 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/taxonomies/topics/sneakers.yaml: -------------------------------------------------------------------------------- 1 | title: Sneakers 2 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 3 | updated_at: 1579284942 4 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/taxonomies/topics/soda.yaml: -------------------------------------------------------------------------------- 1 | title: Soda 2 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 3 | updated_at: 1579284946 4 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/trees/collections/british/pages.yaml: -------------------------------------------------------------------------------- 1 | tree: 2 | - 3 | entry: d1969705-fe5f-4b39-b99a-e93df3309695 4 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/trees/collections/default/pages.yaml: -------------------------------------------------------------------------------- 1 | tree: 2 | - 3 | entry: home 4 | - 5 | entry: 62136fa2-9e5c-4c38-a894-a2753f02f5ff 6 | - 7 | entry: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63 8 | - 9 | entry: f5a53468-017e-4725-b5b6-a745df7e94cb 10 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/trees/collections/french/pages.yaml: -------------------------------------------------------------------------------- 1 | tree: 2 | - 3 | entry: 3ea1f4aa-c9f2-4c5a-b7bc-e4ceed34dc87 4 | - 5 | entry: 7d105969-e5ff-49b3-99ab-3d330f9695e9 6 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/content/trees/collections/italian/pages.yaml: -------------------------------------------------------------------------------- 1 | tree: 2 | - 3 | entry: 4aa3ea1f-c9f2-4c5a-b7bc-d34dc87e4cee 4 | - 5 | entry: 9697d105-e5ff-49b3-99ab-f9695e93d330 6 | -------------------------------------------------------------------------------- /tests/Fixtures/site-localized/resources/sites.yaml: -------------------------------------------------------------------------------- 1 | default: 2 | name: English 3 | locale: en_US 4 | url: / 5 | french: 6 | name: French 7 | locale: fr_FR 8 | url: /fr/ 9 | italian: 10 | name: Italian 11 | locale: it_IT 12 | url: /it/ 13 | british: 14 | name: British 15 | locale: en_GB 16 | url: /en-gb/ 17 | -------------------------------------------------------------------------------- /tests/Fixtures/site/assets/img/coffee-mug.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site/assets/img/coffee-mug.jpg -------------------------------------------------------------------------------- /tests/Fixtures/site/assets/img/stetson.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site/assets/img/stetson.jpg -------------------------------------------------------------------------------- /tests/Fixtures/site/config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Default Cloud Filesystem Disk 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Many applications store files both locally and in the cloud. For this 24 | | reason, you may specify a default "cloud" driver here. This driver 25 | | will be bound as the Cloud disk implementation in the container. 26 | | 27 | */ 28 | 29 | 'cloud' => env('FILESYSTEM_CLOUD', 's3'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Filesystem Disks 34 | |-------------------------------------------------------------------------- 35 | | 36 | | Here you may configure as many filesystem "disks" as you wish, and you 37 | | may even configure multiple disks of the same driver. Defaults have 38 | | been setup for each driver as an example of the required options. 39 | | 40 | | Supported Drivers: "local", "ftp", "s3", "rackspace" 41 | | 42 | */ 43 | 44 | 'disks' => [ 45 | 46 | 'local' => [ 47 | 'driver' => 'local', 48 | 'root' => storage_path('app'), 49 | ], 50 | 51 | 'public' => [ 52 | 'driver' => 'local', 53 | 'root' => storage_path('app/public'), 54 | 'url' => env('APP_URL').'/storage', 55 | 'visibility' => 'public', 56 | ], 57 | 58 | 's3' => [ 59 | 'driver' => 's3', 60 | 'key' => env('AWS_ACCESS_KEY_ID'), 61 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 62 | 'region' => env('AWS_DEFAULT_REGION'), 63 | 'bucket' => env('AWS_BUCKET'), 64 | 'url' => env('AWS_URL'), 65 | ], 66 | 67 | 'assets' => [ 68 | 'driver' => 'local', 69 | 'root' => base_path('assets'), 70 | 'url' => '/assets', 71 | 'visibility' => 'public', 72 | ], 73 | 74 | ], 75 | 76 | ]; 77 | -------------------------------------------------------------------------------- /tests/Fixtures/site/config/statamic/stache.php: -------------------------------------------------------------------------------- 1 | true, 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may configure which stores are used inside the Stache. 26 | | 27 | */ 28 | 29 | 'stores' => [ 30 | 31 | 'taxonomies' => [ 32 | 'class' => Stores\TaxonomiesStore::class, 33 | 'directory' => base_path('content/taxonomies'), 34 | ], 35 | 36 | 'terms' => [ 37 | 'class' => Stores\TermsStore::class, 38 | 'directory' => base_path('content/taxonomies'), 39 | ], 40 | 41 | 'collections' => [ 42 | 'class' => Stores\CollectionsStore::class, 43 | 'directory' => base_path('content/collections'), 44 | ], 45 | 46 | 'entries' => [ 47 | 'class' => Stores\EntriesStore::class, 48 | 'directory' => base_path('content/collections'), 49 | ], 50 | 51 | 'navigation' => [ 52 | 'class' => Stores\NavigationStore::class, 53 | 'directory' => base_path('content/navigation'), 54 | ], 55 | 56 | 'globals' => [ 57 | 'class' => Stores\GlobalsStore::class, 58 | 'directory' => base_path('content/globals'), 59 | ], 60 | 61 | 'asset-containers' => [ 62 | 'class' => Stores\AssetContainersStore::class, 63 | 'directory' => base_path('content/assets'), 64 | ], 65 | 66 | 'users' => [ 67 | 'class' => Stores\UsersStore::class, 68 | 'directory' => base_path('users'), 69 | ], 70 | 71 | ], 72 | 73 | /* 74 | |-------------------------------------------------------------------------- 75 | | Indexes 76 | |-------------------------------------------------------------------------- 77 | | 78 | | Here you may define any additional indexes that will be inherited 79 | | by each store in the Stache. You may also define indexes on a 80 | | per-store level by adding an "indexes" key to its config. 81 | | 82 | */ 83 | 84 | 'indexes' => [ 85 | // 86 | ], 87 | 88 | ]; 89 | -------------------------------------------------------------------------------- /tests/Fixtures/site/config/statamic/users.php: -------------------------------------------------------------------------------- 1 | 'file', 19 | 20 | 'repositories' => [ 21 | 22 | 'file' => [ 23 | 'driver' => 'file', 24 | 'paths' => [ 25 | 'users' => base_path('users'), 26 | 'roles' => resource_path('users/roles.yaml'), 27 | 'groups' => resource_path('users/groups.yaml'), 28 | ], 29 | ], 30 | 31 | 'eloquent' => [ 32 | 'driver' => 'eloquent', 33 | ], 34 | 35 | ], 36 | 37 | /* 38 | |-------------------------------------------------------------------------- 39 | | Avatars 40 | |-------------------------------------------------------------------------- 41 | | 42 | | User avatars are initials by default, with custom options for services 43 | | like Gravatar.com. 44 | | 45 | | Supported: "initials", "gravatar", or a custom class name. 46 | | 47 | */ 48 | 49 | 'avatars' => 'initials', 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | New User Roles 54 | |-------------------------------------------------------------------------- 55 | | 56 | | When registering new users through the user:register_form tag, these 57 | | roles will automatically be applied to your newly created users. 58 | | 59 | */ 60 | 61 | 'new_user_roles' => [ 62 | // 63 | ], 64 | 65 | /* 66 | |-------------------------------------------------------------------------- 67 | | Password Brokers 68 | |-------------------------------------------------------------------------- 69 | | 70 | | When resetting passwords, Statamic uses an appropriate password broker. 71 | | Here you may define which broker should be used for each situation. 72 | | You may want a longer expiry for user activations, for example. 73 | | 74 | */ 75 | 76 | 'passwords' => [ 77 | 'resets' => config('auth.defaults.passwords'), 78 | 'activations' => config('auth.defaults.passwords'), 79 | ], 80 | 81 | ]; 82 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site/content/assets/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site/content/assets/assets.yaml: -------------------------------------------------------------------------------- 1 | title: Assets 2 | disk: assets -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site/content/collections/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/articles.yaml: -------------------------------------------------------------------------------- 1 | title: Articles 2 | route: '{slug}' 3 | template: articles.show 4 | mount: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63 5 | taxonomies: 6 | - topics 7 | revisions: false 8 | date: true 9 | date_behavior: 10 | past: public 11 | future: private 12 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/articles/1994-07-05.magic.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'The Magic Happens at 7 1/2 Pumps' 3 | topics: 4 | - sneakers 5 | excerpt: 'It took me 2 years, 1 month, and 21 days to save up for a pair of Reebok Pumps. When I finally got them, they didn''t work as advertised. Or did they?' 6 | id: af43e0fb-a338-4433-b60a-3bed773be341 7 | --- 8 | Ever since the day Dee Brown pumped up his Reeboks and went on to win the 1991 NBA Slam Dunk Contest, I had been saving to buy a pair. 9 | 10 | It took me 2 years, 1 month, and 21 days, but I'm a proud owner of those black, white, and orange Reebok Pump Omni Lights. 11 | 12 | ![Reebok Pump Omni Lights](/assets/content/reebok-pumps.jpg) 13 | 14 | Only, they didn't work as advertised. The commercials promised that with just a few pumps and I'd soar like Jordan, like an eagle, like a feather on the wind. In reality, I lost 2mm on my vertical jump because they're heavier than my previous kicks. I was devastated, but determined. 15 | 16 | I hunted down a [VHS tape](https://www.youtube.com/watch?v=6uD8ZqkoM5E) of the dunk contest and watched it a dozen times. It was undeniable! Dee Brown lined up for a dunk bit first paused to reach down, pump his Reeboks, and immediately dazzled the crowd. This was no fluke. It was the shoes. I studied the footage. Closely, carefully, and methodically. 17 | 18 | At first it appeared that Dee pumped his sneakers 10 or 11 times. He really went to town on those things. But neither 10 pumps nor 11 pumps made any difference for me. In fact, 11 pumps started to cut off my circulation which one time caused me to stumble and fall into a chain link fence which left diamond shape marks on my face for the better part of a day. 19 | 20 | So I went full scientific method. In order, I tried: 21 | 22 | - 8 pumps 3 times 23 | - 9 pumps 3 times 24 | - 10 pumps 5 times 25 | - 11 pumps 5 times 26 | - 12 pumps once, even though 11 was already too many 27 | 28 | **Nothing.** Shame. Regret. I had spent almost 2 years of allowance on these sneakers! But then I noticed something. I was reviewing Dee's footage and even though the VHS tape was worn and tracking poorly from all the use, I saw it. 3 missed pumps and one single half pump. It's not clear if his fingers were sweaty and he mis-pumped a few times or perhaps he was masking the secret to his greatness. Either way, the secret knowledge was mine, and just time too because my VHS tape was worn thin and nearly unplayable. 29 | 30 | **The magic happens at 7 1/2 pumps.** 31 | 32 | With Dee and Reebok's secret knowledge in hand, I could dunk! I could soar! I began playing street ball downtown for money, and started to rake it in. I made friends more easily than any point in my life and enemies even easilier. I found I, just like Dee Brown, had to mask the number of pumps lest my competitors gain the hard-earned secret to my success. 33 | 34 | > “Where'd you learn how to jump like that, kid?” 35 | 36 | I spun around to see NBA legend Clyde Drexler towering over me. I had just schooled a trio of posers in a rousing game of 3-on-1 and had literally dunked over two of them at once. 37 | 38 | "Oh you know, here and there." I replied. He eyed my pumps. I eyed his pumps. We made eye content and something of a shared secret passed between us. The corner of his mouth cracked upwards in a smirk. "I expect I'll be seeing you in a few years, kid." 39 | 40 | I expect he shall. I expect very much indeed. 41 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/articles/1996-08-16.nectar.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: 'Nectar of the Gods' 3 | topics: 4 | - soda 5 | excerpt: 'The time had come. We had seen the commercials. This was our first foray into the underground competitive world of Surge.' 6 | id: 8e4b4e60-5dfb-47b0-a2d7-a904d64aeb80 7 | --- 8 | The day started just like any other. Wake up at 5:30am, brush my teeth, bathe in a tub of warm milk, and trim my toenails while quietly resenting the fact that _Flipper_ was on Nickelodeon at this hour instead of _Rocko's Modern Life_. That would have to wait until 5:30*pm* for that, and I am impatient. 9 | 10 | In truth, the day would likely be spent slogging my way through _Gumby_, _Rugrats_, _Muppet Babies_, _Allegra's Window_, _Gullah Gullah Island_, _Eureeka's Castle_, and numerous other shows fit for my little sister before I could hang with Rocko. But I digress. My life was about to change. 11 | 12 | The doorbell rang. It was 11am and I opened the door to see my friend Matt standing there with a maniacal grin on his face. Behind him, toppled furniture was scattered about my yard and a dozen neighborhood kids were arranged in a haphazard circle. In the center of this ring of humans stood a tall pedestal upon which rested a cylindrical and metallic green can. 13 | 14 | The time had come. We had seen the commercials. This was our first foray into the [underground competitive world](https://www.youtube.com/watch?v=CTY8hrvFck8) of Fully Loaded Citrus Sodas with Carbos. 15 | 16 | **Off to the side someone screamed the single word that would forever alter the course my life.** 17 | 18 | > “Surge!!!” 19 | 20 | As if bolt of lightning struck us all at once, we sprinted — nay, _hurled_ our bodies towards the pedestal without regard for life or limb. The collision of human bodies could be heard 6 blocks away as fists swung and hands clawed, hair tore away in chunks, buttons flew from plaid hoodies tied around waists, and sneakers took to the air, loose of their foots. 21 | 22 | I can't say how, or at what cost, but my hand closed around the ice cold can first. It was mine. The crowd fell back, subservient to the victor like the days of Sparticus, Crixus, and Marcus Attilius. I cracked the tab and a cool spray of citrus coated those lucky enough to be close. I tossed my head back and from the height of my upwards and outstretched arm, poured the sweet nectar of the gods down my throat. 23 | 24 | ![Surge](/assets/content/surge.jpg) 25 | 26 | ## Wherein I left my body 27 | 28 | I could hear a symphony from on high, replete with horns, trumpets, harps, and one very faint ukulele. My soul lifted up out of me and I was carried away in a torrent of joy. I looked down and for a brief moment I could see my body before a wave of carbo-laden sucrose crashed over my consciousness. 29 | 30 | I lost all sense of time. Did I surf the seas of maltodextrin for a minute? An hour? A year? Was Yellow #5 my brother? Truly I could not tell you, for I do not know. 31 | 32 | ## Wherein I returned 33 | 34 | My body was transformed. Lean muscle rippled with unbridled strength and my vision had become sharp and keen. My mind raced with access to deep wells of new knowledge and wisdom. I surveyed my lawn, the neighborhood, and my subordinates and knew my life would never be the same. 35 | 36 | **Victory is sweet. Surge is sweeter.** 37 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/articles/1996-11-18.dance.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: '''Dance Like No One is Watching'' Is Bad Advice' 3 | topics: 4 | - dance 5 | excerpt: 'The Macarena is an international hit & dance craze. The song is inspired by flamenco dancer Diana Herrera''s beauty, but do you know where the dance came from?' 6 | id: 7ac0bdda-1b84-45f8-ac52-2575dd7e8251 7 | --- 8 | The Macarena by Los Del Rio (Remixed by the Bayside Boys) has been #1 on the charts for 14 weeks in a row. 9 | 10 | It's an international hit and dance craze. Rumor has it that the band spotted a beautiful flamenco dancer named Diana Patricia Cubillan Herrera at a private party held by the Venezuelan empresario in Venezuela. Her beauty and grace inspired them to write the song, and the rest is history. 11 | 12 | But do you know where the dance featured in their [music video](https://www.youtube.com/watch?v=MXVx6yJQbn8) (released earlier this year) came from? No, of course you don't. 13 | 14 | ## It happened in Rio 15 | 16 | Last spring I was vacationing in Rio with my family. We had been there a few weeks, staying in a friend of the family's villa in the quiet area of Lagoa. 17 | 18 | ![Lagoa](/assets/content/lagoa.jpg) 19 | 20 | My sisters were out kayaking on the lake just after sunrise one morning and I had just finished a bit of yoga on the roof to limber up. My mother always told me to dance like no one is watching, so I had grown accustom to practicing my soul moves without care for anyone passing by. 21 | 22 | I had just finished my series of self-healing moves focused on loving and hugging yourself when two older men in black suits waved up at me. 23 | 24 | > “Buenos movimientos, chico!” 25 | 26 | I waved back and shouted my thanks. They went on with their day, and I with mine and soon I forgot about the exchange. 27 | 28 | The next day they were back. And the next. On the fourth day they had a small crowd with them and a video camera – one of those fancy new handheld ones that used the little mini tapes. I wanted one of those. 29 | 30 | I finished my movements quickly and headed down the back stairs to meet these would-be fans. But when I rounded the corner they were gone. 31 | 32 | I didn't see them again after that. I asked around the neighborhood and discovered that they were a famous Spanish musical duo on an extended tour through South America. 33 | 34 | Imagine my surprise when the Macarena dance took the world by storm. I don't begrudge the world my moves – they have such meaning packed into them and everyone with an open mind can learn their lessons – but I never got so much as a thank you, nor did I earn a dime. 35 | 36 | ## The worst part 37 | 38 | The part of this story that bums me out the most, however, is that now when I dance my soul dance, people think I'm following a fad. Now I must be certain no one is watching when I dance. 39 | 40 | **Oh, how I've longed to share my story!** I thank you for listening. May you live long and dance your own dance without care or consequence. 41 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/pages.yaml: -------------------------------------------------------------------------------- 1 | title: Pages 2 | revisions: false 3 | route: '{parent_uri}/{slug}' 4 | structure: 5 | root: true 6 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/pages/about.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: About 3 | subtitle: The Best About Page 4 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 5 | updated_at: 1579284102 6 | template: page 7 | id: 62136fa2-9e5c-4c38-a894-a2753f02f5ff 8 | --- 9 | I'm just a kid living in the 90's, writing articles in his secret public journal wonder if someday, somewhere in the future, they will be read by someone. 10 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/pages/articles.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Articles 3 | template: articles.index 4 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 5 | updated_at: 1579283552 6 | id: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63 7 | --- 8 | These are my various writings. Some might say they are cool. -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/pages/home.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Home 3 | template: page 4 | subtitle: 'I see pride. I see power.' 5 | updated_by: b6c037ad-5bcc-41a8-a455-9ab54573f689 6 | updated_at: 1606223924 7 | id: home 8 | --- 9 | I see a bad-ass mother. 10 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/collections/pages/topics.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Topics 3 | template: topics/index 4 | updated_by: ea0c21bd-9703-4bb1-9fed-58ec0e129dd7 5 | updated_at: 1579534416 6 | id: f5a53468-017e-4725-b5b6-a745df7e94cb 7 | --- 8 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/globals/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site/content/globals/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site/content/globals/settings.yaml: -------------------------------------------------------------------------------- 1 | id: 9242876a-41c4-42f8-96f8-ac92d6025406 2 | title: Settings 3 | data: 4 | site_name: 'Cool Writings' 5 | social: 6 | - 7 | name: Twitter 8 | url: 'https://twitter.com/jackmcdade' 9 | icon: site/social-icons/twitter.svg 10 | - 11 | name: Github 12 | url: 'https://github.com/statamic/starter-kit-cool-writings' 13 | icon: site/social-icons/github.svg 14 | - 15 | name: Email 16 | url: 'mailto:jack@statamic.com' 17 | icon: site/social-icons/email.svg 18 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/navigation/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site/content/navigation/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site/content/taxonomies/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/statamic/seo-pro/fd9e6caaf4a715b0f4a804acd59470ee884e6a59/tests/Fixtures/site/content/taxonomies/.gitkeep -------------------------------------------------------------------------------- /tests/Fixtures/site/content/taxonomies/topics.yaml: -------------------------------------------------------------------------------- 1 | title: Topics 2 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/taxonomies/topics/dance.yaml: -------------------------------------------------------------------------------- 1 | title: Dance 2 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 3 | updated_at: 1579284933 4 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/taxonomies/topics/sneakers.yaml: -------------------------------------------------------------------------------- 1 | title: Sneakers 2 | template: page 3 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 4 | updated_at: 1579284942 5 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/taxonomies/topics/soda.yaml: -------------------------------------------------------------------------------- 1 | title: Soda 2 | updated_by: 96300192-873c-4615-b992-157508a8d7c5 3 | updated_at: 1579284946 4 | -------------------------------------------------------------------------------- /tests/Fixtures/site/content/trees/collections/pages.yaml: -------------------------------------------------------------------------------- 1 | tree: 2 | - 3 | entry: home 4 | - 5 | entry: 62136fa2-9e5c-4c38-a894-a2753f02f5ff 6 | - 7 | entry: b9e4bfe3-9c12-4553-b7ef-f43c22ffaa63 8 | - 9 | entry: f5a53468-017e-4725-b5b6-a745df7e94cb 10 | -------------------------------------------------------------------------------- /tests/Fixtures/site/resources/sites.yaml: -------------------------------------------------------------------------------- 1 | default: 2 | name: English 3 | locale: en_US 4 | url: / 5 | -------------------------------------------------------------------------------- /tests/Fixtures/views/antlers/errors/404.antlers.html: -------------------------------------------------------------------------------- 1 |

antlers

2 |

404!

3 | -------------------------------------------------------------------------------- /tests/Fixtures/views/antlers/layout.antlers.html: -------------------------------------------------------------------------------- 1 | {{ seo_pro:meta }} 2 | {{ template_content }} 3 | -------------------------------------------------------------------------------- /tests/Fixtures/views/antlers/page.antlers.html: -------------------------------------------------------------------------------- 1 |

antlers

2 | -------------------------------------------------------------------------------- /tests/Fixtures/views/blade-components/components/layout.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | @seo_pro('meta') 5 | 6 | 7 | {{ $slot }} 8 | 9 | 10 | -------------------------------------------------------------------------------- /tests/Fixtures/views/blade-components/errors/404.blade.php: -------------------------------------------------------------------------------- 1 | 2 |

blade-components

3 |

404!

4 |
5 | -------------------------------------------------------------------------------- /tests/Fixtures/views/blade-components/page.blade.php: -------------------------------------------------------------------------------- 1 | 2 |

blade-components

3 |
4 | -------------------------------------------------------------------------------- /tests/Fixtures/views/blade/errors/404.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layout') 2 |

blade

3 |

404!

4 | -------------------------------------------------------------------------------- /tests/Fixtures/views/blade/layout.blade.php: -------------------------------------------------------------------------------- 1 | @seo_pro('meta') 2 | @yield('content') 3 | -------------------------------------------------------------------------------- /tests/Fixtures/views/blade/page.blade.php: -------------------------------------------------------------------------------- 1 | @extends('layout') 2 |

blade

3 | -------------------------------------------------------------------------------- /tests/Localized/CascadeTest.php: -------------------------------------------------------------------------------- 1 | set('statamic.editions.pro', true); 19 | $app['config']->set('statamic.system.multisite', true); 20 | } 21 | 22 | /** @test */ 23 | public function it_generates_seo_cascade_for_canonical_url_and_alternate_locales() 24 | { 25 | $entry = Entry::findByUri('/about', 'italian')->entry(); 26 | 27 | $data = (new Cascade) 28 | ->with(SiteDefaults::load()->all()) 29 | ->withCurrent($entry) 30 | ->get(); 31 | 32 | $this->assertEquals('http://cool-runnings.com/it/about', $data['canonical_url']); 33 | $this->assertEquals('it', $data['current_hreflang']); 34 | 35 | $this->assertEquals([ 36 | 'en' => 'http://cool-runnings.com/about', 37 | 'fr' => 'http://cool-runnings.com/fr/about', 38 | ], collect($data['alternate_locales'])->pluck('url', 'hreflang')->all()); 39 | } 40 | 41 | /** @test */ 42 | public function it_generates_seo_cascade_for_canonical_url_and_handles_duplicate_alternate_hreflangs() 43 | { 44 | $entry = Entry::findByUri('/', 'italian')->entry(); 45 | 46 | $data = (new Cascade) 47 | ->with(SiteDefaults::load()->all()) 48 | ->withCurrent($entry) 49 | ->get(); 50 | 51 | $this->assertEquals('http://cool-runnings.com/it', $data['canonical_url']); 52 | $this->assertEquals('it', $data['current_hreflang']); 53 | 54 | $this->assertEquals([ 55 | 'en-us' => 'http://cool-runnings.com', 56 | 'en-gb' => 'http://cool-runnings.com/en-gb', 57 | 'fr' => 'http://cool-runnings.com/fr', 58 | ], collect($data['alternate_locales'])->pluck('url', 'hreflang')->all()); 59 | } 60 | 61 | /** @test */ 62 | public function it_generates_seo_cascade_for_canonical_url_and_handles_duplicate_current_hreflang() 63 | { 64 | $entry = Entry::findByUri('/', 'default')->entry(); 65 | 66 | $data = (new Cascade) 67 | ->with(SiteDefaults::load()->all()) 68 | ->withCurrent($entry) 69 | ->get(); 70 | 71 | $this->assertEquals('http://cool-runnings.com', $data['canonical_url']); 72 | $this->assertEquals('en-us', $data['current_hreflang']); 73 | 74 | $this->assertEquals([ 75 | 'en-gb' => 'http://cool-runnings.com/en-gb', 76 | 'fr' => 'http://cool-runnings.com/fr', 77 | 'it' => 'http://cool-runnings.com/it', 78 | ], collect($data['alternate_locales'])->pluck('url', 'hreflang')->all()); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tests/ViewScenarios.php: -------------------------------------------------------------------------------- 1 | files->copyDirectory(__DIR__.'/Fixtures/views/'.$viewType, resource_path('views-seo-pro')); 24 | 25 | return $this; 26 | } 27 | 28 | public function cleanUpViews() 29 | { 30 | if ($this->files->exists($folder = resource_path('views-seo-pro'))) { 31 | $this->files->deleteDirectory($folder); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import laravel from 'laravel-vite-plugin'; 3 | import vue from '@vitejs/plugin-vue2'; 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | laravel({ 8 | input: [ 9 | 'resources/js/cp.js', 10 | 'resources/css/cp.css' 11 | ], 12 | refresh: true, 13 | publicDirectory: 'resources/dist', 14 | hotFile: 'resources/dist/hot', 15 | }), 16 | vue(), 17 | ], 18 | }); 19 | --------------------------------------------------------------------------------