refactor(modules): extract castopod parts into a modules/ folder for a scalable HMVC structure

- create Admin, Analytics, Auth, Fediverse and Install modules in the root modules/ folder
- rename
ActivityPub to Fediverse
This commit is contained in:
Yassine Doghri 2021-08-23 11:05:16 +00:00
parent 94872f2338
commit 5083cd2fda
268 changed files with 4220 additions and 2185 deletions

View File

@ -15,8 +15,8 @@
#--------------------------------------------------------------------
app.baseURL="https://YOUR_DOMAIN_NAME/"
app.mediaBaseURL="https://YOUR_MEDIA_DOMAIN_NAME/"
app.adminGateway="cp-admin"
app.authGateway="cp-auth"
admin.gateway="cp-admin"
auth.gateway="cp-auth"
#--------------------------------------------------------------------
# Database configuration

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace Config;
use ActivityPub\Config\ActivityPub as ActivityPubBase;
use App\Libraries\NoteObject;
class ActivityPub extends ActivityPubBase
{
/**
* --------------------------------------------------------------------
* ActivityPub Objects
* --------------------------------------------------------------------
*/
public string $noteObject = NoteObject::class;
/**
* --------------------------------------------------------------------
* Default avatar and cover images
* --------------------------------------------------------------------
*/
public string $defaultAvatarImagePath = 'media/castopod-avatar-default_thumbnail.jpg';
public string $defaultAvatarImageMimetype = 'image/jpeg';
public string $defaultCoverImagePath = 'media/castopod-cover-default.jpg';
public string $defaultCoverImageMimetype = 'image/jpeg';
}

View File

@ -427,28 +427,4 @@ class App extends BaseConfig
* Defines the root folder for media files storage
*/
public string $mediaRoot = 'media';
/**
* --------------------------------------------------------------------------
* Admin gateway
* --------------------------------------------------------------------------
* Defines a base route for all admin pages
*/
public string $adminGateway = 'cp-admin';
/**
* --------------------------------------------------------------------------
* Auth gateway
* --------------------------------------------------------------------------
* Defines a base route for all authentication related pages
*/
public string $authGateway = 'cp-auth';
/**
* --------------------------------------------------------------------------
* Install gateway
* --------------------------------------------------------------------------
* Defines a base route for instance installation
*/
public string $installGateway = 'cp-install';
}

View File

@ -43,6 +43,12 @@ class Autoload extends AutoloadConfig
*/
public $psr4 = [
APP_NAMESPACE => APPPATH,
'Modules' => ROOTPATH . 'modules',
'Modules\Admin' => ROOTPATH . 'modules/Admin',
'Modules\Auth' => ROOTPATH . 'modules/Auth',
'Modules\Analytics' => ROOTPATH . 'modules/Analytics',
'Modules\Install' => ROOTPATH . 'modules/Install',
'Modules\Fediverse' => ROOTPATH . 'modules/Fediverse',
'Config' => APPPATH . 'Config',
'ActivityPub' => APPPATH . 'Libraries/ActivityPub',
'Analytics' => APPPATH . 'Libraries/Analytics',

View File

@ -6,9 +6,9 @@ namespace Config;
use App\Entities\Actor;
use App\Entities\Post;
use App\Entities\User;
use CodeIgniter\Events\Events;
use CodeIgniter\Exceptions\FrameworkException;
use Modules\Auth\Entities\User;
/*
* --------------------------------------------------------------------

View File

@ -4,12 +4,12 @@ declare(strict_types=1);
namespace Config;
use ActivityPub\Filters\ActivityPubFilter;
use App\Filters\PermissionFilter;
use CodeIgniter\Config\BaseConfig;
use CodeIgniter\Filters\CSRF;
use CodeIgniter\Filters\DebugToolbar;
use CodeIgniter\Filters\Honeypot;
use Modules\Auth\Filters\PermissionFilter;
use Modules\Fediverse\Filters\ActivityPubFilter;
use Myth\Auth\Filters\LoginFilter;
use Myth\Auth\Filters\RoleFilter;
@ -70,7 +70,7 @@ class Filters extends BaseConfig
$this->filters = [
'login' => [
'before' => [config('App')->adminGateway . '*'],
'before' => [config('Admin') ->gateway . '*', config('Analytics') ->gateway . '*'],
],
];
}

View File

@ -54,675 +54,20 @@ $routes->get('/', 'HomeController::index', [
'as' => 'home',
]);
// Install Wizard route
$routes->group(config('App')->installGateway, function ($routes): void {
$routes->get('/', 'InstallController', [
'as' => 'install',
]);
$routes->post('instance-config', 'InstallController::attemptInstanceConfig', [
'as' => 'instance-config',
]);
$routes->post('database-config', 'InstallController::attemptDatabaseConfig', [
'as' => 'database-config',
]);
$routes->post('cache-config', 'InstallController::attemptCacheConfig', [
'as' => 'cache-config',
]);
$routes->post(
'create-superadmin',
'InstallController::attemptCreateSuperAdmin',
[
'as' => 'create-superadmin',
],
);
});
$routes->get('.well-known/platforms', 'Platform');
// Admin area
$routes->group(
config('App')
->adminGateway,
[
'namespace' => 'App\Controllers\Admin',
],
function ($routes): void {
$routes->get('/', 'HomeController', [
'as' => 'admin',
]);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'PersonController', [
'as' => 'person-list',
'filter' => 'permission:person-list',
]);
$routes->get('new', 'PersonController::create', [
'as' => 'person-create',
'filter' => 'permission:person-create',
]);
$routes->post('new', 'PersonController::attemptCreate', [
'filter' => 'permission:person-create',
]);
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PersonController::view/$1', [
'as' => 'person-view',
'filter' => 'permission:person-view',
]);
$routes->get('edit', 'PersonController::edit/$1', [
'as' => 'person-edit',
'filter' => 'permission:person-edit',
]);
$routes->post('edit', 'PersonController::attemptEdit/$1', [
'filter' => 'permission:person-edit',
]);
$routes->add('delete', 'PersonController::delete/$1', [
'as' => 'person-delete',
'filter' => 'permission:person-delete',
]);
});
});
// Podcasts
$routes->group('podcasts', function ($routes): void {
$routes->get('/', 'PodcastController::list', [
'as' => 'podcast-list',
]);
$routes->get('new', 'PodcastController::create', [
'as' => 'podcast-create',
'filter' => 'permission:podcasts-create',
]);
$routes->post('new', 'PodcastController::attemptCreate', [
'filter' => 'permission:podcasts-create',
]);
$routes->get('import', 'PodcastImportController', [
'as' => 'podcast-import',
'filter' => 'permission:podcasts-import',
]);
$routes->post('import', 'PodcastImportController::attemptImport', [
'filter' => 'permission:podcasts-import',
]);
// Podcast
// Use ids in admin area to help permission and group lookups
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PodcastController::view/$1', [
'as' => 'podcast-view',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->get('edit', 'PodcastController::edit/$1', [
'as' => 'podcast-edit',
'filter' => 'permission:podcast-edit',
]);
$routes->post('edit', 'PodcastController::attemptEdit/$1', [
'filter' => 'permission:podcast-edit',
]);
$routes->get('delete', 'PodcastController::delete/$1', [
'as' => 'podcast-delete',
'filter' => 'permission:podcasts-delete',
]);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'PodcastPersonController/$1', [
'as' => 'podcast-person-manage',
'filter' => 'permission:podcast-edit',
]);
$routes->post(
'/',
'PodcastPersonController::attemptAdd/$1',
[
'filter' => 'permission:podcast-edit',
],
);
$routes->get(
'(:num)/remove',
'PodcastPersonController::remove/$1/$2',
[
'as' => 'podcast-person-remove',
'filter' => 'permission:podcast-edit',
],
);
});
$routes->group('analytics', function ($routes): void {
$routes->get('/', 'PodcastController::viewAnalytics/$1', [
'as' => 'podcast-analytics',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->get(
'webpages',
'PodcastController::viewAnalyticsWebpages/$1',
[
'as' => 'podcast-analytics-webpages',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'locations',
'PodcastController::viewAnalyticsLocations/$1',
[
'as' => 'podcast-analytics-locations',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'unique-listeners',
'PodcastController::viewAnalyticsUniqueListeners/$1',
[
'as' => 'podcast-analytics-unique-listeners',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'listening-time',
'PodcastController::viewAnalyticsListeningTime/$1',
[
'as' => 'podcast-analytics-listening-time',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'time-periods',
'PodcastController::viewAnalyticsTimePeriods/$1',
[
'as' => 'podcast-analytics-time-periods',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'players',
'PodcastController::viewAnalyticsPlayers/$1',
[
'as' => 'podcast-analytics-players',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
});
// Podcast episodes
$routes->group('episodes', function ($routes): void {
$routes->get('/', 'EpisodeController::list/$1', [
'as' => 'episode-list',
'filter' =>
'permission:episodes-list,podcast_episodes-list',
]);
$routes->get('new', 'EpisodeController::create/$1', [
'as' => 'episode-create',
'filter' => 'permission:podcast_episodes-create',
]);
$routes->post(
'new',
'EpisodeController::attemptCreate/$1',
[
'filter' => 'permission:podcast_episodes-create',
],
);
// Episode
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'EpisodeController::view/$1/$2', [
'as' => 'episode-view',
'filter' =>
'permission:episodes-view,podcast_episodes-view',
]);
$routes->get('edit', 'EpisodeController::edit/$1/$2', [
'as' => 'episode-edit',
'filter' => 'permission:podcast_episodes-edit',
]);
$routes->post(
'edit',
'EpisodeController::attemptEdit/$1/$2',
[
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'publish',
'EpisodeController::publish/$1/$2',
[
'as' => 'episode-publish',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'publish',
'EpisodeController::attemptPublish/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'publish-edit',
'EpisodeController::publishEdit/$1/$2',
[
'as' => 'episode-publish_edit',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'publish-edit',
'EpisodeController::attemptPublishEdit/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'publish-cancel',
'EpisodeController::publishCancel/$1/$2',
[
'as' => 'episode-publish-cancel',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'unpublish',
'EpisodeController::unpublish/$1/$2',
[
'as' => 'episode-unpublish',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'unpublish',
'EpisodeController::attemptUnpublish/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'delete',
'EpisodeController::delete/$1/$2',
[
'as' => 'episode-delete',
'filter' =>
'permission:podcast_episodes-delete',
],
);
$routes->get(
'transcript-delete',
'EpisodeController::transcriptDelete/$1/$2',
[
'as' => 'transcript-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'chapters-delete',
'EpisodeController::chaptersDelete/$1/$2',
[
'as' => 'chapters-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'soundbites',
'EpisodeController::soundbitesEdit/$1/$2',
[
'as' => 'soundbites-edit',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->post(
'soundbites',
'EpisodeController::soundbitesAttemptEdit/$1/$2',
[
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'soundbites/(:num)/delete',
'EpisodeController::soundbiteDelete/$1/$2/$3',
[
'as' => 'soundbite-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'embeddable-player',
'EpisodeController::embeddablePlayer/$1/$2',
[
'as' => 'embeddable-player-add',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'EpisodePersonController/$1/$2', [
'as' => 'episode-person-manage',
'filter' => 'permission:podcast_episodes-edit',
]);
$routes->post(
'/',
'EpisodePersonController::attemptAdd/$1/$2',
[
'filter' =>
'permission:podcast_episodes-edit',
],
);
$routes->get(
'(:num)/remove',
'EpisodePersonController::remove/$1/$2/$3',
[
'as' => 'episode-person-remove',
'filter' =>
'permission:podcast_episodes-edit',
],
);
});
$routes->group('comments', function ($routes): void {
$routes->post(
'new',
'EpisodeController::attemptCommentCreate/$1/$2',
[
'as' => 'comment-attempt-create',
'filter' => 'permission:podcast-manage_publications',
]
);
$routes->post(
'(:uuid)/reply',
'EpisodeController::attemptCommentReply/$1/$2/$3',
[
'as' => 'comment-attempt-reply',
'filter' => 'permission:podcast-manage_publications',
]
);
$routes->post(
'delete',
'EpisodeController::attemptCommentDelete/$1/$2',
[
'as' => 'comment-attempt-delete',
'filter' => 'permission:podcast-manage_publications',
]
);
});
});
});
// Podcast contributors
$routes->group('contributors', function ($routes): void {
$routes->get('/', 'ContributorController::list/$1', [
'as' => 'contributor-list',
'filter' =>
'permission:podcasts-view,podcast-manage_contributors',
]);
$routes->get('add', 'ContributorController::add/$1', [
'as' => 'contributor-add',
'filter' => 'permission:podcast-manage_contributors',
]);
$routes->post(
'add',
'ContributorController::attemptAdd/$1',
[
'filter' =>
'permission:podcast-manage_contributors',
],
);
// Contributor
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'ContributorController::view/$1/$2', [
'as' => 'contributor-view',
'filter' =>
'permission:podcast-manage_contributors',
]);
$routes->get(
'edit',
'ContributorController::edit/$1/$2',
[
'as' => 'contributor-edit',
'filter' =>
'permission:podcast-manage_contributors',
],
);
$routes->post(
'edit',
'ContributorController::attemptEdit/$1/$2',
[
'filter' =>
'permission:podcast-manage_contributors',
],
);
$routes->get(
'remove',
'ContributorController::remove/$1/$2',
[
'as' => 'contributor-remove',
'filter' =>
'permission:podcast-manage_contributors',
],
);
});
});
$routes->group('platforms', function ($routes): void {
$routes->get(
'/',
'PodcastPlatformController::platforms/$1/podcasting',
[
'as' => 'platforms-podcasting',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'social',
'PodcastPlatformController::platforms/$1/social',
[
'as' => 'platforms-social',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'funding',
'PodcastPlatformController::platforms/$1/funding',
[
'as' => 'platforms-funding',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->post(
'save/(:platformType)',
'PodcastPlatformController::attemptPlatformsUpdate/$1/$2',
[
'as' => 'platforms-save',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'(:slug)/podcast-platform-remove',
'PodcastPlatformController::removePodcastPlatform/$1/$2',
[
'as' => 'podcast-platform-remove',
'filter' => 'permission:podcast-manage_platforms',
],
);
});
});
});
// Instance wide Fediverse config
$routes->group('fediverse', function ($routes): void {
$routes->get('/', 'FediverseController::dashboard', [
'as' => 'fediverse-dashboard',
]);
$routes->get(
'blocked-actors',
'FediverseController::blockedActors',
[
'as' => 'fediverse-blocked-actors',
'filter' => 'permission:fediverse-block_actors',
],
);
$routes->get(
'blocked-domains',
'FediverseController::blockedDomains',
[
'as' => 'fediverse-blocked-domains',
'filter' => 'permission:fediverse-block_domains',
],
);
});
// Pages
$routes->group('pages', function ($routes): void {
$routes->get('/', 'PageController::list', [
'as' => 'page-list',
]);
$routes->get('new', 'PageController::create', [
'as' => 'page-create',
'filter' => 'permission:pages-manage',
]);
$routes->post('new', 'PageController::attemptCreate', [
'filter' => 'permission:pages-manage',
]);
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PageController::view/$1', [
'as' => 'page-view',
]);
$routes->get('edit', 'PageController::edit/$1', [
'as' => 'page-edit',
'filter' => 'permission:pages-manage',
]);
$routes->post('edit', 'PageController::attemptEdit/$1', [
'filter' => 'permission:pages-manage',
]);
$routes->get('delete', 'PageController::delete/$1', [
'as' => 'page-delete',
'filter' => 'permission:pages-manage',
]);
});
});
// Users
$routes->group('users', function ($routes): void {
$routes->get('/', 'UserController::list', [
'as' => 'user-list',
'filter' => 'permission:users-list',
]);
$routes->get('new', 'UserController::create', [
'as' => 'user-create',
'filter' => 'permission:users-create',
]);
$routes->post('new', 'UserController::attemptCreate', [
'filter' => 'permission:users-create',
]);
// User
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'UserController::view/$1', [
'as' => 'user-view',
'filter' => 'permission:users-view',
]);
$routes->get('edit', 'UserController::edit/$1', [
'as' => 'user-edit',
'filter' => 'permission:users-manage_authorizations',
]);
$routes->post('edit', 'UserController::attemptEdit/$1', [
'filter' => 'permission:users-manage_authorizations',
]);
$routes->get('ban', 'UserController::ban/$1', [
'as' => 'user-ban',
'filter' => 'permission:users-manage_bans',
]);
$routes->get('unban', 'UserController::unBan/$1', [
'as' => 'user-unban',
'filter' => 'permission:users-manage_bans',
]);
$routes->get(
'force-pass-reset',
'UserController::forcePassReset/$1',
[
'as' => 'user-force_pass_reset',
'filter' => 'permission:users-force_pass_reset',
],
);
$routes->get('delete', 'UserController::delete/$1', [
'as' => 'user-delete',
'filter' => 'permission:users-delete',
]);
});
});
// My account
$routes->group('my-account', function ($routes): void {
$routes->get('/', 'MyAccountController', [
'as' => 'my-account',
]);
$routes->get(
'change-password',
'MyAccountController::changePassword/$1',
[
'as' => 'change-password',
],
);
$routes->post('change-password', 'MyAccountController::attemptChange/$1');
});
},
);
/**
* Overwriting Myth:auth routes file
*/
$routes->group(config('App')->authGateway, function ($routes): void {
// Login/out
$routes->get('login', 'AuthController::login', [
'as' => 'login',
]);
$routes->post('login', 'AuthController::attemptLogin');
$routes->get('logout', 'AuthController::logout', [
'as' => 'logout',
]);
// Registration
$routes->get('register', 'AuthController::register', [
'as' => 'register',
]);
$routes->post('register', 'AuthController::attemptRegister');
// Activation
$routes->get('activate-account', 'AuthController::activateAccount', [
'as' => 'activate-account',
]);
$routes->get(
'resend-activate-account',
'AuthController::resendActivateAccount',
[
'as' => 'resend-activate-account',
],
);
// Forgot/Resets
$routes->get('forgot', 'AuthController::forgotPassword', [
'as' => 'forgot',
]);
$routes->post('forgot', 'AuthController::attemptForgot');
$routes->get('reset-password', 'AuthController::resetPassword', [
'as' => 'reset-password',
]);
$routes->post('reset-password', 'AuthController::attemptReset');
});
// Podcast's Public routes
$routes->group('@(:podcastHandle)', function ($routes): void {
$routes->get('/', 'PodcastController::activity/$1', [
'as' => 'podcast-activity',
]);
// override default ActivityPub Library's actor route
// override default Fediverse Library's actor route
$routes->options('/', 'ActivityPubController::preflight');
$routes->get('/', 'PodcastController::activity/$1', [
'as' => 'actor',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'ActivityPub\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'ActorController/$1',
],
'application/podcast-activity+json' => [
@ -730,7 +75,7 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
'controller-method' => 'PodcastController::podcastActor/$1',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'ActivityPub\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'ActorController/$1',
],
],
@ -839,13 +184,8 @@ $routes->get('/pages/(:slug)', 'PageController/$1', [
'as' => 'page',
]);
// interacting as an actor
$routes->post('interact-as-actor', 'AuthController::attemptInteractAsActor', [
'as' => 'interact-as-actor',
]);
/**
* Overwriting ActivityPub routes file
* Overwriting Fediverse routes file
*/
$routes->group('@(:podcastHandle)', function ($routes): void {
$routes->post('posts/new', 'PostController::attemptCreate/$1', [
@ -860,11 +200,11 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
'as' => 'post',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'ActivityPub\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController/$2',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'ActivityPub\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController/$2',
],
],
@ -874,11 +214,11 @@ $routes->group('@(:podcastHandle)', function ($routes): void {
'as' => 'post-replies',
'alternate-content' => [
'application/activity+json' => [
'namespace' => 'ActivityPub\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::replies/$2',
],
'application/ld+json; profile="https://www.w3.org/ns/activitystreams' => [
'namespace' => 'ActivityPub\Controllers',
'namespace' => 'Modules\Fediverse\Controllers',
'controller-method' => 'PostController::replies/$2',
],
],

View File

@ -4,20 +4,14 @@ declare(strict_types=1);
namespace Config;
use App\Authorization\FlatAuthorization;
use App\Authorization\GroupModel;
use App\Authorization\PermissionModel;
use App\Libraries\Breadcrumb;
use App\Libraries\Negotiate;
use App\Libraries\Router;
use App\Libraries\Vite;
use App\Models\UserModel;
use CodeIgniter\Config\BaseService;
use CodeIgniter\HTTP\Request;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\Model;
use CodeIgniter\Router\RouteCollectionInterface;
use Myth\Auth\Models\LoginModel;
/**
* Services Configuration file.
@ -69,70 +63,6 @@ class Services extends BaseService
return new Negotiate($request);
}
/**
* @return mixed
*/
public static function authentication(
string $lib = 'local',
Model $userModel = null,
Model $loginModel = null,
bool $getShared = true
) {
if ($getShared) {
return self::getSharedInstance('authentication', $lib, $userModel, $loginModel);
}
// config() checks first in app/Config
$config = config('Auth');
$class = $config->authenticationLibs[$lib];
$instance = new $class($config);
if ($userModel === null) {
$userModel = new UserModel();
}
if ($loginModel === null) {
$loginModel = new LoginModel();
}
return $instance->setUserModel($userModel)
->setLoginModel($loginModel);
}
/**
* @return mixed|$this
*/
public static function authorization(
Model $groupModel = null,
Model $permissionModel = null,
Model $userModel = null,
bool $getShared = true
) {
if ($getShared) {
return self::getSharedInstance('authorization', $groupModel, $permissionModel, $userModel);
}
if ($groupModel === null) {
$groupModel = new GroupModel();
}
if ($permissionModel === null) {
$permissionModel = new PermissionModel();
}
/* @phpstan-ignore-next-line */
$instance = new FlatAuthorization($groupModel, $permissionModel);
if ($userModel === null) {
$userModel = new UserModel();
}
/* @phpstan-ignore-next-line */
return $instance->setUserModel($userModel);
}
public static function breadcrumb(bool $getShared = true): Breadcrumb
{
if ($getShared) {

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Controllers;
use ActivityPub\Controllers\ActorController as ActivityPubActorController;
use Analytics\AnalyticsTrait;
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Controllers\ActorController as ActivityPubActorController;
class ActorController extends ActivityPubActorController
{

View File

@ -10,11 +10,6 @@ declare(strict_types=1);
namespace App\Controllers;
use ActivityPub\Entities\Actor;
use ActivityPub\Objects\OrderedCollectionObject;
use ActivityPub\Objects\OrderedCollectionPage;
use Analytics\AnalyticsTrait;
use App\Controllers\Admin\BaseController;
use App\Entities\Episode;
use App\Entities\EpisodeComment;
use App\Entities\Podcast;
@ -25,6 +20,10 @@ use App\Models\PodcastModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\Response;
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Entities\Actor;
use Modules\Fediverse\Objects\OrderedCollectionObject;
use Modules\Fediverse\Objects\OrderedCollectionPage;
class EpisodeCommentController extends BaseController
{

View File

@ -10,9 +10,6 @@ declare(strict_types=1);
namespace App\Controllers;
use ActivityPub\Objects\OrderedCollectionObject;
use ActivityPub\Objects\OrderedCollectionPage;
use Analytics\AnalyticsTrait;
use App\Entities\Episode;
use App\Entities\Podcast;
use App\Libraries\NoteObject;
@ -24,6 +21,9 @@ use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\Response;
use CodeIgniter\HTTP\ResponseInterface;
use Config\Services;
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Objects\OrderedCollectionObject;
use Modules\Fediverse\Objects\OrderedCollectionPage;
use SimpleXMLElement;
class EpisodeController extends BaseController

View File

@ -10,9 +10,6 @@ declare(strict_types=1);
namespace App\Controllers;
use ActivityPub\Objects\OrderedCollectionObject;
use ActivityPub\Objects\OrderedCollectionPage;
use Analytics\AnalyticsTrait;
use App\Entities\Podcast;
use App\Libraries\PodcastActor;
use App\Libraries\PodcastEpisode;
@ -21,6 +18,9 @@ use App\Models\PodcastModel;
use App\Models\PostModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\Response;
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Objects\OrderedCollectionObject;
use Modules\Fediverse\Objects\OrderedCollectionPage;
class PodcastController extends BaseController
{

View File

@ -10,9 +10,6 @@ declare(strict_types=1);
namespace App\Controllers;
use ActivityPub\Controllers\PostController as ActivityPubPostController;
use ActivityPub\Entities\Post as ActivityPubPost;
use Analytics\AnalyticsTrait;
use App\Entities\Actor;
use App\Entities\Podcast;
use App\Entities\Post as CastopodPost;
@ -23,6 +20,9 @@ use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use CodeIgniter\HTTP\URI;
use CodeIgniter\I18n\Time;
use Modules\Analytics\AnalyticsTrait;
use Modules\Fediverse\Controllers\PostController as ActivityPubPostController;
use Modules\Fediverse\Entities\Post as ActivityPubPost;
class PostController extends ActivityPubPostController
{

View File

@ -10,7 +10,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace Analytics\Database\Migrations;
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;

View File

@ -10,7 +10,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace ActivityPub\Database\Migrations;
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Entities;
use ActivityPub\Entities\Actor as ActivityPubActor;
use App\Models\PodcastModel;
use Modules\Fediverse\Entities\Actor as ActivityPubActor;
use RuntimeException;
/**

View File

@ -19,6 +19,7 @@ use App\Models\UserModel;
use CodeIgniter\Entity\Entity;
use CodeIgniter\I18n\Time;
use League\CommonMark\CommonMarkConverter;
use Modules\Auth\Entities\User;
use RuntimeException;
/**

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Entities;
use ActivityPub\Entities\Post as ActivityPubPost;
use App\Models\EpisodeModel;
use Modules\Fediverse\Entities\Post as ActivityPubPost;
use RuntimeException;
/**

View File

@ -8,10 +8,9 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
use ActivityPub\Entities\Actor;
use App\Entities\User;
use CodeIgniter\Database\Exceptions\DataException;
use Config\Services;
use Modules\Auth\Entities\User;
use Modules\Fediverse\Entities\Actor;
if (! function_exists('user')) {
/**
@ -19,7 +18,7 @@ if (! function_exists('user')) {
*/
function user(): ?User
{
$authenticate = Services::authentication();
$authenticate = service('authentication');
$authenticate->check();
return $authenticate->user();
}
@ -31,7 +30,7 @@ if (! function_exists('set_interact_as_actor')) {
*/
function set_interact_as_actor(int $actorId): void
{
$authenticate = Services::authentication();
$authenticate = service('authentication');
$authenticate->check();
$session = session();
@ -56,7 +55,7 @@ if (! function_exists('interact_as_actor_id')) {
*/
function interact_as_actor_id(): int
{
$authenticate = Services::authentication();
$authenticate = service('authentication');
$authenticate->check();
$session = session();
@ -70,7 +69,7 @@ if (! function_exists('interact_as_actor')) {
*/
function interact_as_actor(): Actor | false
{
$authenticate = Services::authentication();
$authenticate = service('authentication');
$authenticate->check();
$session = session();

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
return [
'label' => 'breadcrumb',
config('App')
->adminGateway => 'Home',
config('Admin')
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',
'contributors' => 'contributors',

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
return [
'label' => 'Fil dAriane',
config('App')
->adminGateway => 'Accueil',
config('Admin')
->gateway => 'Accueil',
'podcasts' => 'podcasts',
'episodes' => 'épisodes',
'contributors' => 'contributeurs',

View File

@ -1,37 +0,0 @@
<?php
declare(strict_types=1);
namespace Analytics\Config;
use CodeIgniter\Config\BaseConfig;
class Analytics extends BaseConfig
{
/**
* Gateway to analytic routes. By default, all analytics routes will be under `/analytics` path
*/
public string $gateway = 'analytics';
/**
* --------------------------------------------------------------------
* Route filters options
* --------------------------------------------------------------------
* @var array<string, string>
*/
public array $routeFilters = [
'analytics-full-data' => '',
'analytics-data' => '',
'analytics-filtered-data' => '',
];
/**
* get the full audio file
*
* @param string|string[] $audioFilePath
*/
public function getAudioFileUrl(string | array $audioFilePath): string
{
return base_url($audioFilePath);
}
}

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Libraries;
use ActivityPub\Core\ObjectType;
use App\Entities\EpisodeComment;
use Modules\Fediverse\Core\ObjectType;
class CommentObject extends ObjectType
{

View File

@ -10,15 +10,15 @@ declare(strict_types=1);
namespace App\Libraries;
use ActivityPub\Objects\NoteObject as ActivityPubNoteObject;
use App\Entities\Post;
use Modules\Fediverse\Objects\NoteObject as ActivityPubNoteObject;
class NoteObject extends ActivityPubNoteObject
{
/**
* @param Post $post
*/
public function __construct(\ActivityPub\Entities\Post $post)
public function __construct($post)
{
parent::__construct($post);

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Libraries;
use ActivityPub\Objects\ActorObject;
use App\Entities\Podcast;
use Modules\Fediverse\Objects\ActorObject;
class PodcastActor extends ActorObject
{

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Libraries;
use ActivityPub\Core\ObjectType;
use App\Entities\Episode;
use Modules\Fediverse\Core\ObjectType;
class PodcastEpisode extends ObjectType
{

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Models;
use ActivityPub\Models\ActorModel as ActivityPubActorModel;
use App\Entities\Actor;
use Modules\Fediverse\Models\ActorModel as ActivityPubActorModel;
class ActorModel extends ActivityPubActorModel
{

View File

@ -10,11 +10,11 @@ declare(strict_types=1);
namespace App\Models;
use ActivityPub\Activities\CreateActivity;
use App\Entities\EpisodeComment;
use App\Libraries\CommentObject;
use CodeIgniter\Database\BaseBuilder;
use Michalsn\Uuid\UuidModel;
use Modules\Fediverse\Activities\CreateActivity;
class EpisodeCommentModel extends UuidModel
{

View File

@ -10,12 +10,12 @@ declare(strict_types=1);
namespace App\Models;
use ActivityPub\Activities\LikeActivity;
use ActivityPub\Activities\UndoActivity;
use ActivityPub\Entities\Actor;
use App\Entities\EpisodeComment;
use App\Entities\Like;
use Michalsn\Uuid\UuidModel;
use Modules\Fediverse\Activities\LikeActivity;
use Modules\Fediverse\Activities\UndoActivity;
use Modules\Fediverse\Entities\Actor;
class LikeModel extends UuidModel
{

View File

@ -385,7 +385,7 @@ class PodcastModel extends Model
// delete all cache for podcast actor
cache()
->deleteMatching(config('ActivityPub') ->cachePrefix . "actor#{$podcast->actor_id}*");
->deleteMatching(config('Fediverse') ->cachePrefix . "actor#{$podcast->actor_id}*");
// delete model requests cache, includes feed / query / episode lists, etc.
cache()

View File

@ -10,8 +10,8 @@ declare(strict_types=1);
namespace App\Models;
use ActivityPub\Models\PostModel as ActivityPubPostModel;
use App\Entities\Post;
use Modules\Fediverse\Models\PostModel as ActivityPubPostModel;
class PostModel extends ActivityPubPostModel
{

View File

@ -10,7 +10,7 @@ declare(strict_types=1);
namespace App\Models;
use App\Entities\User;
use Modules\Auth\Entities\User;
use Myth\Auth\Models\UserModel as MythAuthUserModel;
class UserModel extends MythAuthUserModel

View File

@ -51,8 +51,8 @@ to help you kickstart your contribution.
app.baseURL="http://localhost:8080/"
app.mediaBaseURL="http://localhost:8080/"
app.adminGateway="cp-admin"
app.authGateway="cp-auth"
admin.gateway="cp-admin"
auth.gateway="cp-auth"
database.default.hostname="mariadb"
database.default.database="castopod"

View File

@ -11,6 +11,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
// alternative to CLI arguments, easier to maintain and extend
$parameters->set(Option::PATHS, [
__DIR__ . '/app',
__DIR__ . '/modules',
__DIR__ . '/tests',
__DIR__ . '/public',
]);
@ -18,6 +19,7 @@ return static function (ContainerConfigurator $containerConfigurator): void {
$parameters->set(Option::SKIP, [
// TODO: restrict some rules for views?
__DIR__ . '/app/Views/*',
__DIR__ . '/modules/**/Views/*',
// skip specific generated files
__DIR__ . '/app/Language/*/PersonsTaxonomy.php',

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Modules\Admin\Config;
use CodeIgniter\Config\BaseConfig;
class Admin extends BaseConfig
{
/**
* --------------------------------------------------------------------------
* Admin gateway
* --------------------------------------------------------------------------
* Defines a base route for all admin pages
*/
public string $gateway = 'cp-admin';
}

View File

@ -0,0 +1,597 @@
<?php
declare(strict_types=1);
namespace Modules\Admin\Config;
$routes = service('routes');
// Admin area routes
$routes->group(
config('Admin')
->gateway,
[
'namespace' => 'Modules\Admin\Controllers',
],
function ($routes): void {
$routes->get('/', 'HomeController', [
'as' => 'admin',
]);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'PersonController', [
'as' => 'person-list',
'filter' => 'permission:person-list',
]);
$routes->get('new', 'PersonController::create', [
'as' => 'person-create',
'filter' => 'permission:person-create',
]);
$routes->post('new', 'PersonController::attemptCreate', [
'filter' => 'permission:person-create',
]);
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PersonController::view/$1', [
'as' => 'person-view',
'filter' => 'permission:person-view',
]);
$routes->get('edit', 'PersonController::edit/$1', [
'as' => 'person-edit',
'filter' => 'permission:person-edit',
]);
$routes->post('edit', 'PersonController::attemptEdit/$1', [
'filter' => 'permission:person-edit',
]);
$routes->add('delete', 'PersonController::delete/$1', [
'as' => 'person-delete',
'filter' => 'permission:person-delete',
]);
});
});
// Podcasts
$routes->group('podcasts', function ($routes): void {
$routes->get('/', 'PodcastController::list', [
'as' => 'podcast-list',
]);
$routes->get('new', 'PodcastController::create', [
'as' => 'podcast-create',
'filter' => 'permission:podcasts-create',
]);
$routes->post('new', 'PodcastController::attemptCreate', [
'filter' => 'permission:podcasts-create',
]);
$routes->get('import', 'PodcastImportController', [
'as' => 'podcast-import',
'filter' => 'permission:podcasts-import',
]);
$routes->post('import', 'PodcastImportController::attemptImport', [
'filter' => 'permission:podcasts-import',
]);
// Podcast
// Use ids in admin area to help permission and group lookups
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PodcastController::view/$1', [
'as' => 'podcast-view',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->get('edit', 'PodcastController::edit/$1', [
'as' => 'podcast-edit',
'filter' => 'permission:podcast-edit',
]);
$routes->post('edit', 'PodcastController::attemptEdit/$1', [
'filter' => 'permission:podcast-edit',
]);
$routes->get('delete', 'PodcastController::delete/$1', [
'as' => 'podcast-delete',
'filter' => 'permission:podcasts-delete',
]);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'PodcastPersonController/$1', [
'as' => 'podcast-person-manage',
'filter' => 'permission:podcast-edit',
]);
$routes->post(
'/',
'PodcastPersonController::attemptAdd/$1',
[
'filter' => 'permission:podcast-edit',
],
);
$routes->get(
'(:num)/remove',
'PodcastPersonController::remove/$1/$2',
[
'as' => 'podcast-person-remove',
'filter' => 'permission:podcast-edit',
],
);
});
$routes->group('analytics', function ($routes): void {
$routes->get('/', 'PodcastController::viewAnalytics/$1', [
'as' => 'podcast-analytics',
'filter' => 'permission:podcasts-view,podcast-view',
]);
$routes->get(
'webpages',
'PodcastController::viewAnalyticsWebpages/$1',
[
'as' => 'podcast-analytics-webpages',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'locations',
'PodcastController::viewAnalyticsLocations/$1',
[
'as' => 'podcast-analytics-locations',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'unique-listeners',
'PodcastController::viewAnalyticsUniqueListeners/$1',
[
'as' => 'podcast-analytics-unique-listeners',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'listening-time',
'PodcastController::viewAnalyticsListeningTime/$1',
[
'as' => 'podcast-analytics-listening-time',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'time-periods',
'PodcastController::viewAnalyticsTimePeriods/$1',
[
'as' => 'podcast-analytics-time-periods',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
$routes->get(
'players',
'PodcastController::viewAnalyticsPlayers/$1',
[
'as' => 'podcast-analytics-players',
'filter' => 'permission:podcasts-view,podcast-view',
],
);
});
// Podcast episodes
$routes->group('episodes', function ($routes): void {
$routes->get('/', 'EpisodeController::list/$1', [
'as' => 'episode-list',
'filter' =>
'permission:episodes-list,podcast_episodes-list',
]);
$routes->get('new', 'EpisodeController::create/$1', [
'as' => 'episode-create',
'filter' => 'permission:podcast_episodes-create',
]);
$routes->post(
'new',
'EpisodeController::attemptCreate/$1',
[
'filter' => 'permission:podcast_episodes-create',
],
);
// Episode
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'EpisodeController::view/$1/$2', [
'as' => 'episode-view',
'filter' =>
'permission:episodes-view,podcast_episodes-view',
]);
$routes->get('edit', 'EpisodeController::edit/$1/$2', [
'as' => 'episode-edit',
'filter' => 'permission:podcast_episodes-edit',
]);
$routes->post(
'edit',
'EpisodeController::attemptEdit/$1/$2',
[
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'publish',
'EpisodeController::publish/$1/$2',
[
'as' => 'episode-publish',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'publish',
'EpisodeController::attemptPublish/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'publish-edit',
'EpisodeController::publishEdit/$1/$2',
[
'as' => 'episode-publish_edit',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'publish-edit',
'EpisodeController::attemptPublishEdit/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'publish-cancel',
'EpisodeController::publishCancel/$1/$2',
[
'as' => 'episode-publish-cancel',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'unpublish',
'EpisodeController::unpublish/$1/$2',
[
'as' => 'episode-unpublish',
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->post(
'unpublish',
'EpisodeController::attemptUnpublish/$1/$2',
[
'filter' =>
'permission:podcast-manage_publications',
],
);
$routes->get(
'delete',
'EpisodeController::delete/$1/$2',
[
'as' => 'episode-delete',
'filter' =>
'permission:podcast_episodes-delete',
],
);
$routes->get(
'transcript-delete',
'EpisodeController::transcriptDelete/$1/$2',
[
'as' => 'transcript-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'chapters-delete',
'EpisodeController::chaptersDelete/$1/$2',
[
'as' => 'chapters-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'soundbites',
'EpisodeController::soundbitesEdit/$1/$2',
[
'as' => 'soundbites-edit',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->post(
'soundbites',
'EpisodeController::soundbitesAttemptEdit/$1/$2',
[
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'soundbites/(:num)/delete',
'EpisodeController::soundbiteDelete/$1/$2/$3',
[
'as' => 'soundbite-delete',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->get(
'embeddable-player',
'EpisodeController::embeddablePlayer/$1/$2',
[
'as' => 'embeddable-player-add',
'filter' => 'permission:podcast_episodes-edit',
],
);
$routes->group('persons', function ($routes): void {
$routes->get('/', 'EpisodePersonController/$1/$2', [
'as' => 'episode-person-manage',
'filter' => 'permission:podcast_episodes-edit',
]);
$routes->post(
'/',
'EpisodePersonController::attemptAdd/$1/$2',
[
'filter' =>
'permission:podcast_episodes-edit',
],
);
$routes->get(
'(:num)/remove',
'EpisodePersonController::remove/$1/$2/$3',
[
'as' => 'episode-person-remove',
'filter' =>
'permission:podcast_episodes-edit',
],
);
});
$routes->group('comments', function ($routes): void {
$routes->post(
'new',
'EpisodeController::attemptCommentCreate/$1/$2',
[
'as' => 'comment-attempt-create',
'filter' => 'permission:podcast-manage_publications',
]
);
$routes->post(
'(:uuid)/reply',
'EpisodeController::attemptCommentReply/$1/$2/$3',
[
'as' => 'comment-attempt-reply',
'filter' => 'permission:podcast-manage_publications',
]
);
$routes->post(
'delete',
'EpisodeController::attemptCommentDelete/$1/$2',
[
'as' => 'comment-attempt-delete',
'filter' => 'permission:podcast-manage_publications',
]
);
});
});
});
// Podcast contributors
$routes->group('contributors', function ($routes): void {
$routes->get('/', 'ContributorController::list/$1', [
'as' => 'contributor-list',
'filter' =>
'permission:podcasts-view,podcast-manage_contributors',
]);
$routes->get('add', 'ContributorController::add/$1', [
'as' => 'contributor-add',
'filter' => 'permission:podcast-manage_contributors',
]);
$routes->post(
'add',
'ContributorController::attemptAdd/$1',
[
'filter' =>
'permission:podcast-manage_contributors',
],
);
// Contributor
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'ContributorController::view/$1/$2', [
'as' => 'contributor-view',
'filter' =>
'permission:podcast-manage_contributors',
]);
$routes->get(
'edit',
'ContributorController::edit/$1/$2',
[
'as' => 'contributor-edit',
'filter' =>
'permission:podcast-manage_contributors',
],
);
$routes->post(
'edit',
'ContributorController::attemptEdit/$1/$2',
[
'filter' =>
'permission:podcast-manage_contributors',
],
);
$routes->get(
'remove',
'ContributorController::remove/$1/$2',
[
'as' => 'contributor-remove',
'filter' =>
'permission:podcast-manage_contributors',
],
);
});
});
$routes->group('platforms', function ($routes): void {
$routes->get(
'/',
'PodcastPlatformController::platforms/$1/podcasting',
[
'as' => 'platforms-podcasting',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'social',
'PodcastPlatformController::platforms/$1/social',
[
'as' => 'platforms-social',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'funding',
'PodcastPlatformController::platforms/$1/funding',
[
'as' => 'platforms-funding',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->post(
'save/(:platformType)',
'PodcastPlatformController::attemptPlatformsUpdate/$1/$2',
[
'as' => 'platforms-save',
'filter' => 'permission:podcast-manage_platforms',
],
);
$routes->get(
'(:slug)/podcast-platform-remove',
'PodcastPlatformController::removePodcastPlatform/$1/$2',
[
'as' => 'podcast-platform-remove',
'filter' => 'permission:podcast-manage_platforms',
],
);
});
});
});
// Instance wide Fediverse config
$routes->group('fediverse', function ($routes): void {
$routes->get('/', 'FediverseController::dashboard', [
'as' => 'fediverse-dashboard',
]);
$routes->get(
'blocked-actors',
'FediverseController::blockedActors',
[
'as' => 'fediverse-blocked-actors',
'filter' => 'permission:fediverse-block_actors',
],
);
$routes->get(
'blocked-domains',
'FediverseController::blockedDomains',
[
'as' => 'fediverse-blocked-domains',
'filter' => 'permission:fediverse-block_domains',
],
);
});
// Pages
$routes->group('pages', function ($routes): void {
$routes->get('/', 'PageController::list', [
'as' => 'page-list',
]);
$routes->get('new', 'PageController::create', [
'as' => 'page-create',
'filter' => 'permission:pages-manage',
]);
$routes->post('new', 'PageController::attemptCreate', [
'filter' => 'permission:pages-manage',
]);
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'PageController::view/$1', [
'as' => 'page-view',
]);
$routes->get('edit', 'PageController::edit/$1', [
'as' => 'page-edit',
'filter' => 'permission:pages-manage',
]);
$routes->post('edit', 'PageController::attemptEdit/$1', [
'filter' => 'permission:pages-manage',
]);
$routes->get('delete', 'PageController::delete/$1', [
'as' => 'page-delete',
'filter' => 'permission:pages-manage',
]);
});
});
// Users
$routes->group('users', function ($routes): void {
$routes->get('/', 'UserController::list', [
'as' => 'user-list',
'filter' => 'permission:users-list',
]);
$routes->get('new', 'UserController::create', [
'as' => 'user-create',
'filter' => 'permission:users-create',
]);
$routes->post('new', 'UserController::attemptCreate', [
'filter' => 'permission:users-create',
]);
// User
$routes->group('(:num)', function ($routes): void {
$routes->get('/', 'UserController::view/$1', [
'as' => 'user-view',
'filter' => 'permission:users-view',
]);
$routes->get('edit', 'UserController::edit/$1', [
'as' => 'user-edit',
'filter' => 'permission:users-manage_authorizations',
]);
$routes->post('edit', 'UserController::attemptEdit/$1', [
'filter' => 'permission:users-manage_authorizations',
]);
$routes->get('ban', 'UserController::ban/$1', [
'as' => 'user-ban',
'filter' => 'permission:users-manage_bans',
]);
$routes->get('unban', 'UserController::unBan/$1', [
'as' => 'user-unban',
'filter' => 'permission:users-manage_bans',
]);
$routes->get(
'force-pass-reset',
'UserController::forcePassReset/$1',
[
'as' => 'user-force_pass_reset',
'filter' => 'permission:users-force_pass_reset',
],
);
$routes->get('delete', 'UserController::delete/$1', [
'as' => 'user-delete',
'filter' => 'permission:users-delete',
]);
});
});
// My account
$routes->group('my-account', function ($routes): void {
$routes->get('/', 'MyAccountController', [
'as' => 'my-account',
]);
$routes->get(
'change-password',
'MyAccountController::changePassword/$1',
[
'as' => 'change-password',
],
);
$routes->post('change-password', 'MyAccountController::attemptChange/$1');
});
},
);

View File

@ -2,7 +2,7 @@
declare(strict_types=1);
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\HTTP\RequestInterface;

View File

@ -8,16 +8,16 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Authorization\GroupModel;
use App\Entities\Podcast;
use App\Entities\User;
use App\Models\PodcastModel;
use App\Models\UserModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use Exception;
use Modules\Auth\Authorization\GroupModel;
use Modules\Auth\Entities\User;
class ContributorController extends BaseController
{
@ -57,7 +57,7 @@ class ContributorController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/contributor/list', $data);
return view('Modules\Admin\Views\contributor\list', $data);
}
public function view(): string
@ -70,7 +70,7 @@ class ContributorController extends BaseController
0 => $this->podcast->title,
1 => $this->user->username,
]);
return view('admin/contributor/view', $data);
return view('Modules\Admin\Views\contributor\view', $data);
}
public function add(): string
@ -106,7 +106,7 @@ class ContributorController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/contributor/add', $data);
return view('Modules\Admin\Views\contributor\add', $data);
}
public function attemptAdd(): RedirectResponse
@ -155,7 +155,7 @@ class ContributorController extends BaseController
0 => $this->podcast->title,
1 => $this->user->username,
]);
return view('admin/contributor/edit', $data);
return view('Modules\Admin\Views\contributor\edit', $data);
}
public function attemptEdit(): RedirectResponse

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Episode;
use App\Entities\EpisodeComment;
@ -77,7 +77,7 @@ class EpisodeController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/episode/list', $data);
return view('Modules\Admin\Views\episode\list', $data);
}
public function view(): string
@ -91,7 +91,7 @@ class EpisodeController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/view', $data);
return view('Modules\Admin\Views\episode\view', $data);
}
public function create(): string
@ -105,7 +105,7 @@ class EpisodeController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/episode/create', $data);
return view('Modules\Admin\Views\episode\create', $data);
}
public function attemptCreate(): RedirectResponse
@ -230,7 +230,7 @@ class EpisodeController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/edit', $data);
return view('Modules\Admin\Views\episode\edit', $data);
}
public function attemptEdit(): RedirectResponse
@ -404,7 +404,7 @@ class EpisodeController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/publish', $data);
return view('Modules\Admin\Views\episode\publish', $data);
}
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
@ -503,7 +503,7 @@ class EpisodeController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/publish_edit', $data);
return view('Modules\Admin\Views\episode\publish_edit', $data);
}
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
@ -632,7 +632,7 @@ class EpisodeController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/unpublish', $data);
return view('Modules\Admin\Views\episode\unpublish', $data);
}
return redirect()->route('episode-view', [$this->podcast->id, $this->episode->id])->with(
@ -704,7 +704,7 @@ class EpisodeController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/soundbites', $data);
return view('Modules\Admin\Views\episode\soundbites', $data);
}
public function soundbitesAttemptEdit(): RedirectResponse
@ -782,7 +782,7 @@ class EpisodeController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/embeddable_player', $data);
return view('Modules\Admin\Views\episode\embeddable_player', $data);
}
public function attemptCommentCreate(): RedirectResponse

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Episode;
use App\Entities\Podcast;
@ -62,7 +62,7 @@ class EpisodePersonController extends BaseController
0 => $this->podcast->title,
1 => $this->episode->title,
]);
return view('admin/episode/persons', $data);
return view('Modules\Admin\Views\episode\persons', $data);
}
public function attemptAdd(): RedirectResponse

View File

@ -8,13 +8,13 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
class FediverseController extends BaseController
{
public function dashboard(): string
{
return view('admin/fediverse/dashboard');
return view('Modules\Admin\Views\fediverse\dashboard');
}
public function blockedActors(): string
@ -24,7 +24,7 @@ class FediverseController extends BaseController
$blockedActors = model('ActorModel')
->getBlockedActors();
return view('admin/fediverse/blocked_actors', [
return view('Modules\Admin\Views\fediverse\blocked_actors', [
'blockedActors' => $blockedActors,
]);
}
@ -36,7 +36,7 @@ class FediverseController extends BaseController
$blockedDomains = model('BlockedDomainModel')
->getBlockedDomains();
return view('admin/fediverse/blocked_domains', [
return view('Modules\Admin\Views\fediverse\blocked_domains', [
'blockedDomains' => $blockedDomains,
]);
}

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use CodeIgniter\HTTP\RedirectResponse;

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Models\UserModel;
use CodeIgniter\HTTP\RedirectResponse;
@ -18,14 +18,14 @@ class MyAccountController extends BaseController
{
public function index(): string
{
return view('admin/my_account/view');
return view('Modules\Admin\Views\my_account\view');
}
public function changePassword(): string
{
helper('form');
return view('admin/my_account/change_password');
return view('Modules\Admin\Views\my_account\change_password');
}
public function attemptChange(): RedirectResponse

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Page;
use App\Models\PageModel;
@ -38,12 +38,12 @@ class PageController extends BaseController
'pages' => (new PageModel())->findAll(),
];
return view('admin/page/list', $data);
return view('Modules\Admin\Views\page\list', $data);
}
public function view(): string
{
return view('admin/page/view', [
return view('Modules\Admin\Views\page\view', [
'page' => $this->page,
]);
}
@ -52,7 +52,7 @@ class PageController extends BaseController
{
helper('form');
return view('admin/page/create');
return view('Modules\Admin\Views\page\create');
}
public function attemptCreate(): RedirectResponse
@ -86,7 +86,7 @@ class PageController extends BaseController
replace_breadcrumb_params([
0 => $this->page->title,
]);
return view('admin/page/edit', [
return view('Modules\Admin\Views\page\edit', [
'page' => $this->page,
]);
}

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Image;
use App\Entities\Person;
@ -41,7 +41,7 @@ class PersonController extends BaseController
'persons' => (new PersonModel())->findAll(),
];
return view('admin/person/list', $data);
return view('Modules\Admin\Views\person\list', $data);
}
public function view(): string
@ -53,14 +53,14 @@ class PersonController extends BaseController
replace_breadcrumb_params([
0 => $this->person->full_name,
]);
return view('admin/person/view', $data);
return view('Modules\Admin\Views\person\view', $data);
}
public function create(): string
{
helper(['form']);
return view('admin/person/create');
return view('Modules\Admin\Views\person\create');
}
public function attemptCreate(): RedirectResponse
@ -113,7 +113,7 @@ class PersonController extends BaseController
replace_breadcrumb_params([
0 => $this->person->full_name,
]);
return view('admin/person/edit', $data);
return view('Modules\Admin\Views\person\edit', $data);
}
public function attemptEdit(): RedirectResponse

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Image;
use App\Entities\Location;
@ -53,7 +53,7 @@ class PodcastController extends BaseController
];
}
return view('admin/podcast/list', $data);
return view('Modules\Admin\Views\podcast\list', $data);
}
public function view(): string
@ -65,7 +65,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/view', $data);
return view('Modules\Admin\Views\podcast\view', $data);
}
public function viewAnalytics(): string
@ -77,7 +77,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/index', $data);
return view('Modules\Admin\Views\podcast\analytics\index', $data);
}
public function viewAnalyticsWebpages(): string
@ -89,7 +89,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/webpages', $data);
return view('Modules\Admin\Views\podcast\analytics\webpages', $data);
}
public function viewAnalyticsLocations(): string
@ -101,7 +101,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/locations', $data);
return view('Modules\Admin\Views\podcast\analytics\locations', $data);
}
public function viewAnalyticsUniqueListeners(): string
@ -113,7 +113,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/unique_listeners', $data);
return view('Modules\Admin\Views\podcast\analytics\unique_listeners', $data);
}
public function viewAnalyticsListeningTime(): string
@ -125,7 +125,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/listening_time', $data);
return view('Modules\Admin\Views\podcast\analytics\listening_time', $data);
}
public function viewAnalyticsTimePeriods(): string
@ -137,7 +137,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/time_periods', $data);
return view('Modules\Admin\Views\podcast\analytics\time_periods', $data);
}
public function viewAnalyticsPlayers(): string
@ -149,7 +149,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/analytics/players', $data);
return view('Modules\Admin\Views\podcast\analytics\players', $data);
}
public function create(): string
@ -165,7 +165,7 @@ class PodcastController extends BaseController
'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE')),
];
return view('admin/podcast/create', $data);
return view('Modules\Admin\Views\podcast\create', $data);
}
public function attemptCreate(): RedirectResponse
@ -274,7 +274,7 @@ class PodcastController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/edit', $data);
return view('Modules\Admin\Views\podcast\edit', $data);
}
public function attemptEdit(): RedirectResponse
@ -364,7 +364,7 @@ class PodcastController extends BaseController
->orderBy('created_at', 'desc')
->findAll($limit);
return view('admin/podcast/latest_episodes', [
return view('Modules\Admin\Views\podcast\latest_episodes', [
'episodes' => $episodes,
]);
}

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Episode;
use App\Entities\Image;
@ -58,7 +58,7 @@ class PodcastImportController extends BaseController
'browserLang' => get_browser_language($this->request->getServer('HTTP_ACCEPT_LANGUAGE')),
];
return view('admin/podcast/import', $data);
return view('Modules\Admin\Views\podcast\import', $data);
}
public function attemptImport(): RedirectResponse

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Podcast;
use App\Models\PersonModel;
@ -49,7 +49,7 @@ class PodcastPersonController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/persons', $data);
return view('Modules\Admin\Views\podcast\persons', $data);
}
public function attemptAdd(): RedirectResponse

View File

@ -8,7 +8,7 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Entities\Podcast;
use App\Models\PlatformModel;
@ -39,7 +39,7 @@ class PodcastPlatformController extends BaseController
public function index(): string
{
return view('admin/podcast/platforms/dashboard');
return view('Modules\Admin\Views\podcast\platforms\dashboard');
}
public function platforms(string $platformType): string
@ -55,7 +55,7 @@ class PodcastPlatformController extends BaseController
replace_breadcrumb_params([
0 => $this->podcast->title,
]);
return view('admin/podcast/platforms', $data);
return view('Modules\Admin\Views\podcast\platforms', $data);
}
public function attemptPlatformsUpdate(string $platformType): RedirectResponse

View File

@ -8,14 +8,14 @@ declare(strict_types=1);
* @link https://castopod.org/
*/
namespace App\Controllers\Admin;
namespace Modules\Admin\Controllers;
use App\Authorization\GroupModel;
use App\Entities\User;
use App\Models\UserModel;
use CodeIgniter\Exceptions\PageNotFoundException;
use CodeIgniter\HTTP\RedirectResponse;
use Config\Services;
use Modules\Auth\Authorization\GroupModel;
use Modules\Auth\Entities\User;
class UserController extends BaseController
{
@ -40,7 +40,7 @@ class UserController extends BaseController
'users' => (new UserModel())->findAll(),
];
return view('admin/user/list', $data);
return view('Modules\Admin\Views\user\list', $data);
}
public function view(): string
@ -52,7 +52,7 @@ class UserController extends BaseController
replace_breadcrumb_params([
0 => $this->user->username,
]);
return view('admin/user/view', $data);
return view('Modules\Admin\Views\user\view', $data);
}
public function create(): string
@ -63,7 +63,7 @@ class UserController extends BaseController
'roles' => (new GroupModel())->getUserRoles(),
];
return view('admin/user/create', $data);
return view('Modules\Admin\Views\user\create', $data);
}
public function attemptCreate(): RedirectResponse
@ -135,7 +135,7 @@ class UserController extends BaseController
replace_breadcrumb_params([
0 => $this->user->username,
]);
return view('admin/user/edit', $data);
return view('Modules\Admin\Views\user\edit', $data);
}
public function attemptEdit(): RedirectResponse

View File

View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'dashboard' => 'Admin dashboard',
'welcome_message' => 'Welcome to the admin area!',
'choose_interact' => 'Choose how to interact',
];

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'label' => 'breadcrumb',
config('Admin')
->gateway => 'Home',
'podcasts' => 'podcasts',
'episodes' => 'episodes',
'contributors' => 'contributors',
'pages' => 'pages',
'add' => 'add',
'new' => 'new',
'edit' => 'edit',
'persons' => 'persons',
'publish' => 'publish',
'publish-edit' => 'edit publication',
'unpublish' => 'unpublish',
'fediverse' => 'fediverse',
'block-lists' => 'block lists',
'users' => 'users',
'my-account' => 'my account',
'change-password' => 'change password',
'import' => 'feed import',
'platforms' => 'platforms',
'social' => 'social networks',
'funding' => 'funding',
'analytics' => 'analytics',
'locations' => 'locations',
'webpages' => 'web pages',
'unique-listeners' => 'unique listeners',
'players' => 'players',
'listening-time' => 'listening time',
'time-periods' => 'time periods',
'soundbites' => 'soundbites',
'embeddable-player' => 'embeddable player',
];

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'by_service_weekly' => 'Episode downloads by service (for the past week)',
'by_player_weekly' => 'Episode downloads by player (for the past week)',
'by_player_yearly' => 'Episode downloads by player (for the past year)',
'by_device_weekly' => 'Episode downloads by device (for the past week)',
'by_os_weekly' => 'Episode downloads by O.S. (for the past week)',
'podcast_by_region' => 'Episode downloads by region (for the past week)',
'unique_daily_listeners' => 'Daily unique listeners',
'unique_monthly_listeners' => 'Monthly unique listeners',
'by_browser' => 'Web pages usage by browser (for the past week)',
'podcast_by_day' => 'Episode daily downloads',
'podcast_by_month' => 'Episode monthly downloads',
'episode_by_day' => 'Episode daily downloads (first 60 days)',
'episode_by_month' => 'Episode monthly downloads',
'episodes_by_day' =>
'5 latest episodes downloads (during their first 60 days)',
'by_country_weekly' => 'Episode downloads by country (for the past week)',
'by_country_yearly' => 'Episode downloads by country (for the past year)',
'by_domain_weekly' => 'Web pages visits by source (for the past week)',
'by_domain_yearly' => 'Web pages visits by source (for the past year)',
'by_entry_page' => 'Web pages visits by landing page (for the past week)',
'podcast_bots' => 'Bots (crawlers)',
'daily_listening_time' => 'Daily cumulative listening time',
'monthly_listening_time' => 'Monthly cumulative listening time',
'by_weekday' => 'By week day (for the past 60 days)',
'by_hour' => 'By time of day (for the past 60 days)',
'podcast_by_bandwidth' => 'Daily used bandwidth (in MB)',
];

View File

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'yes' => 'Yes',
'no' => 'No',
'cancel' => 'Cancel',
'optional' => 'Optional',
'more' => 'More',
'no_data' => 'No data found!',
'close' => 'Close',
'edit' => 'Edit',
'copy' => 'Copy',
'copied' => 'Copied!',
'home' => 'Home',
'explicit' => 'Explicit',
'mediumDate' => '{0,date,medium}',
'powered_by' => 'Powered by {castopod}.',
'actions' => 'Actions',
'pageInfo' => 'Page {currentPage} out of {pageCount}',
'go_back' => 'Go back',
'forms' => [
'editor' => [
'write' => 'Write',
'preview' => 'Preview',
'help' => 'Powered by markdown',
],
'multiSelect' => [
'selectText' => 'Press to select',
'loadingText' => 'Loading...',
'noResultsText' => 'No results found',
'noChoicesText' => 'No choices to choose from',
'maxItemText' => 'Cannot add more items',
],
'image_size_hint' =>
'Image must be squared with at least 1400px wide and tall.',
'upload_file' => 'Upload a file',
'remote_url' => 'Remote URL',
],
'play_episode_button' => [
'play' => 'Play',
'playing' => 'Playing',
],
];

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'podcast_contributors' => 'Podcast contributors',
'view' => "{username}'s contribution to {podcastTitle}",
'add' => 'Add contributor',
'add_contributor' => 'Add a contributor for {0}',
'edit_role' => 'Update role for {0}',
'edit' => 'Edit',
'remove' => 'Remove',
'list' => [
'username' => 'Username',
'role' => 'Role',
],
'form' => [
'user' => 'User',
'user_placeholder' => 'Select a user…',
'role' => 'Role',
'role_placeholder' => 'Select its role…',
'submit_add' => 'Add contributor',
'submit_edit' => 'Update role',
],
'roles' => [
'podcast_admin' => 'Podcast admin',
],
'messages' => [
'removeOwnerContributorError' => "You can't remove the podcast owner!",
'removeContributorSuccess' =>
'You have successfully removed {username} from {podcastTitle}',
'alreadyAddedError' =>
"The contributor you're trying to add has already been added!",
],
];

View File

@ -0,0 +1,264 @@
<?php
declare(strict_types=1);
/**
* ISO 3166 country codes
*
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'AD' => 'Andorra',
'AE' => 'United Arab Emirates',
'AF' => 'Afghanistan',
'AG' => 'Antigua and Barbuda',
'AI' => 'Anguilla',
'AL' => 'Albania',
'AM' => 'Armenia',
'AO' => 'Angola',
'AQ' => 'Antarctica',
'AR' => 'Argentina',
'AS' => 'American Samoa',
'AT' => 'Austria',
'AU' => 'Australia',
'AW' => 'Aruba',
'AX' => 'Åland Islands',
'AZ' => 'Azerbaijan',
'BA' => 'Bosnia and Herzegovina',
'BB' => 'Barbados',
'BD' => 'Bangladesh',
'BE' => 'Belgium',
'BF' => 'Burkina Faso',
'BG' => 'Bulgaria',
'BH' => 'Bahrain',
'BI' => 'Burundi',
'BJ' => 'Benin',
'BL' => 'Saint Barthélemy',
'BM' => 'Bermuda',
'BN' => 'Brunei Darussalam',
'BO' => 'Bolivia, Plurinational State of',
'BQ' => 'Bonaire, Sint Eustatius and Saba',
'BR' => 'Brazil',
'BS' => 'Bahamas',
'BT' => 'Bhutan',
'BV' => 'Bouvet Island',
'BW' => 'Botswana',
'BY' => 'Belarus',
'BZ' => 'Belize',
'CA' => 'Canada',
'CC' => 'Cocos (Keeling) Islands',
'CD' => 'Congo, the Democratic Republic of the',
'CF' => 'Central African Republic',
'CG' => 'Congo',
'CH' => 'Switzerland',
'CI' => "Côte d'Ivoire",
'CK' => 'Cook Islands',
'CL' => 'Chile',
'CM' => 'Cameroon',
'CN' => 'China',
'CO' => 'Colombia',
'CR' => 'Costa Rica',
'CU' => 'Cuba',
'CV' => 'Cape Verde',
'CW' => 'Curaçao',
'CX' => 'Christmas Island',
'CY' => 'Cyprus',
'CZ' => 'Czech Republic',
'DE' => 'Germany',
'DJ' => 'Djibouti',
'DK' => 'Denmark',
'DM' => 'Dominica',
'DO' => 'Dominican Republic',
'DZ' => 'Algeria',
'EC' => 'Ecuador',
'EE' => 'Estonia',
'EG' => 'Egypt',
'EH' => 'Western Sahara',
'ER' => 'Eritrea',
'ES' => 'Spain',
'ET' => 'Ethiopia',
'FI' => 'Finland',
'FJ' => 'Fiji',
'FK' => 'Falkland Islands (Malvinas)',
'FM' => 'Micronesia, Federated States of',
'FO' => 'Faroe Islands',
'FR' => 'France',
'GA' => 'Gabon',
'GB' => 'United Kingdom',
'GD' => 'Grenada',
'GE' => 'Georgia',
'GF' => 'French Guiana',
'GG' => 'Guernsey',
'GH' => 'Ghana',
'GI' => 'Gibraltar',
'GL' => 'Greenland',
'GM' => 'Gambia',
'GN' => 'Guinea',
'GP' => 'Guadeloupe',
'GQ' => 'Equatorial Guinea',
'GR' => 'Greece',
'GS' => 'South Georgia and the South Sandwich Islands',
'GT' => 'Guatemala',
'GU' => 'Guam',
'GW' => 'Guinea-Bissau',
'GY' => 'Guyana',
'HK' => 'Hong Kong',
'HM' => 'Heard Island and McDonald Islands',
'HN' => 'Honduras',
'HR' => 'Croatia',
'HT' => 'Haiti',
'HU' => 'Hungary',
'ID' => 'Indonesia',
'IE' => 'Ireland',
'IL' => 'Israel',
'IM' => 'Isle of Man',
'IN' => 'India',
'IO' => 'British Indian Ocean Territory',
'IQ' => 'Iraq',
'IR' => 'Iran, Islamic Republic of',
'IS' => 'Iceland',
'IT' => 'Italy',
'JE' => 'Jersey',
'JM' => 'Jamaica',
'JO' => 'Jordan',
'JP' => 'Japan',
'KE' => 'Kenya',
'KG' => 'Kyrgyzstan',
'KH' => 'Cambodia',
'KI' => 'Kiribati',
'KM' => 'Comoros',
'KN' => 'Saint Kitts and Nevis',
'KP' => "Korea, Democratic People's Republic of",
'KR' => 'Korea, Republic of',
'KW' => 'Kuwait',
'KY' => 'Cayman Islands',
'KZ' => 'Kazakhstan',
'LA' => "Lao People's Democratic Republic",
'LB' => 'Lebanon',
'LC' => 'Saint Lucia',
'LI' => 'Liechtenstein',
'LK' => 'Sri Lanka',
'LR' => 'Liberia',
'LS' => 'Lesotho',
'LT' => 'Lithuania',
'LU' => 'Luxembourg',
'LV' => 'Latvia',
'LY' => 'Libya',
'MA' => 'Morocco',
'MC' => 'Monaco',
'MD' => 'Moldova, Republic of',
'ME' => 'Montenegro',
'MF' => 'Saint Martin (French part)',
'MG' => 'Madagascar',
'MH' => 'Marshall Islands',
'MK' => 'Macedonia, the Former Yugoslav Republic of',
'ML' => 'Mali',
'MM' => 'Myanmar',
'MN' => 'Mongolia',
'MO' => 'Macao',
'MP' => 'Northern Mariana Islands',
'MQ' => 'Martinique',
'MR' => 'Mauritania',
'MS' => 'Montserrat',
'MT' => 'Malta',
'MU' => 'Mauritius',
'MV' => 'Maldives',
'MW' => 'Malawi',
'MX' => 'Mexico',
'MY' => 'Malaysia',
'MZ' => 'Mozambique',
'N/A' => 'Not Applicable (local IP…)',
'NA' => 'Namibia',
'NC' => 'New Caledonia',
'NE' => 'Niger',
'NF' => 'Norfolk Island',
'NG' => 'Nigeria',
'NI' => 'Nicaragua',
'NL' => 'Netherlands',
'NO' => 'Norway',
'NP' => 'Nepal',
'NR' => 'Nauru',
'NU' => 'Niue',
'NZ' => 'New Zealand',
'OM' => 'Oman',
'PA' => 'Panama',
'PE' => 'Peru',
'PF' => 'French Polynesia',
'PG' => 'Papua New Guinea',
'PH' => 'Philippines',
'PK' => 'Pakistan',
'PL' => 'Poland',
'PM' => 'Saint Pierre and Miquelon',
'PN' => 'Pitcairn',
'PR' => 'Puerto Rico',
'PS' => 'Palestine, State of',
'PT' => 'Portugal',
'PW' => 'Palau',
'PY' => 'Paraguay',
'QA' => 'Qatar',
'RE' => 'Réunion',
'RO' => 'Romania',
'RS' => 'Serbia',
'RU' => 'Russian Federation',
'RW' => 'Rwanda',
'SA' => 'Saudi Arabia',
'SB' => 'Solomon Islands',
'SC' => 'Seychelles',
'SD' => 'Sudan',
'SE' => 'Sweden',
'SG' => 'Singapore',
'SH' => 'Saint Helena, Ascension and Tristan da Cunha',
'SI' => 'Slovenia',
'SJ' => 'Svalbard and Jan Mayen',
'SK' => 'Slovakia',
'SL' => 'Sierra Leone',
'SM' => 'San Marino',
'SN' => 'Senegal',
'SO' => 'Somalia',
'SR' => 'Suriname',
'SS' => 'South Sudan',
'ST' => 'Sao Tome and Principe',
'SV' => 'El Salvador',
'SX' => 'Sint Maarten (Dutch part)',
'SY' => 'Syrian Arab Republic',
'SZ' => 'Swaziland',
'TC' => 'Turks and Caicos Islands',
'TD' => 'Chad',
'TF' => 'French Southern Territories',
'TG' => 'Togo',
'TH' => 'Thailand',
'TJ' => 'Tajikistan',
'TK' => 'Tokelau',
'TL' => 'Timor-Leste',
'TM' => 'Turkmenistan',
'TN' => 'Tunisia',
'TO' => 'Tonga',
'TR' => 'Turkey',
'TT' => 'Trinidad and Tobago',
'TV' => 'Tuvalu',
'TW' => 'Taiwan, Province of China',
'TZ' => 'Tanzania, United Republic of',
'UA' => 'Ukraine',
'UG' => 'Uganda',
'UM' => 'United States Minor Outlying Islands',
'US' => 'United States',
'UY' => 'Uruguay',
'UZ' => 'Uzbekistan',
'VA' => 'Holy See (Vatican City State)',
'VC' => 'Saint Vincent and the Grenadines',
'VE' => 'Venezuela, Bolivarian Republic of',
'VG' => 'Virgin Islands, British',
'VI' => 'Virgin Islands, U.S.',
'VN' => 'Viet Nam',
'VU' => 'Vanuatu',
'WF' => 'Wallis and Futuna',
'WS' => 'Samoa',
'YE' => 'Yemen',
'YT' => 'Mayotte',
'ZA' => 'South Africa',
'ZM' => 'Zambia',
'ZW' => 'Zimbabwe',
];

View File

@ -0,0 +1,174 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'season' => 'Season {seasonNumber}',
'season_abbr' => 'S{seasonNumber}',
'number' => 'Episode {episodeNumber}',
'number_abbr' => 'Ep. {episodeNumber}',
'season_episode' => 'Season {seasonNumber} episode {episodeNumber}',
'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}',
'back_to_episodes' => 'Back to episodes of {podcast}',
'comments' => 'Comments',
'activity' => 'Activity',
'description' => 'Description',
'number_of_comments' => '{numberOfComments, plural,
one {# comment}
other {# comments}
}',
'all_podcast_episodes' => 'All podcast episodes',
'back_to_podcast' => 'Go back to podcast',
'edit' => 'Edit',
'publish' => 'Publish',
'publish_edit' => 'Edit publication',
'unpublish' => 'Unpublish',
'publish_error' => 'Episode is already published.',
'publish_edit_error' => 'Episode is already published.',
'publish_cancel_error' => 'Episode is already published.',
'unpublish_error' => 'Episode is not published.',
'delete' => 'Delete',
'go_to_page' => 'Go to page',
'create' => 'Add an episode',
'publication_status' => [
'published' => 'Published',
'scheduled' => 'Scheduled',
'not_published' => 'Not published',
],
'list' => [
'episode' => 'Episode',
'visibility' => 'Visibility',
'comments' => 'Comments',
'actions' => 'Actions',
],
'form' => [
'warning' =>
'In case of fatal error, try increasing the `memory_limit`, `upload_max_filesize` and `post_max_size` values in your php configuration file then restart your web server.<br />These values must be higher than the audio file you wish to upload.',
'audio_file' => 'Audio file',
'audio_file_hint' => 'Choose an .mp3 or .m4a audio file.',
'info_section_title' => 'Episode info',
'info_section_subtitle' => '',
'image' => 'Cover image',
'image_hint' =>
'If you do not set an image, the podcast cover will be used instead.',
'title' => 'Title',
'title_hint' =>
'Should contain a clear and concise episode name. Do not specify the episode or season numbers here.',
'permalink' => 'Permalink',
'season_number' => 'Season',
'episode_number' => 'Episode',
'type' => [
'label' => 'Type',
'hint' =>
'- <strong>full</strong>: complete content the episode.<br/>- <strong>trailer</strong>: short, promotional piece of content that represents a preview of the current show.<br/>- <strong>bonus</strong>: extra content for the show (for example, behind the scenes info or interviews with the cast) or cross-promotional content for another show.',
'full' => 'Full',
'trailer' => 'Trailer',
'bonus' => 'Bonus',
],
'parental_advisory' => [
'label' => 'Parental advisory',
'hint' => 'Does the episode contain explicit content?',
'undefined' => 'undefined',
'clean' => 'Clean',
'explicit' => 'Explicit',
],
'show_notes_section_title' => 'Show notes',
'show_notes_section_subtitle' =>
'Up to 4000 characters, be clear and concise. Show notes help potential listeners in finding the episode.',
'description' => 'Description',
'description_footer' => 'Description footer',
'description_footer_hint' =>
'This text is added at the end of each episode description, it is a good place to input your social links for example.',
'additional_files_section_title' => 'Additional files',
'additional_files_section_subtitle' =>
'These files may be used by other platforms to provide better experience to your audience.<br />See the {podcastNamespaceLink} for more information.',
'location_section_title' => 'Location',
'location_section_subtitle' => 'What place is this episode about?',
'location_name' => 'Location name or address',
'location_name_hint' => 'This can be a real or fictional location',
'transcript' => 'Transcript or closed captions',
'transcript_hint' => 'Allowed formats are txt, html, srt or json.',
'transcript_file' => 'Transcript file',
'transcript_file_remote_url' => 'Remote url for transcript',
'transcript_file_delete' => 'Delete transcript file',
'chapters' => 'Chapters',
'chapters_hint' => 'File must be in JSON Chapters format.',
'chapters_file' => 'Chapters file',
'chapters_file_remote_url' => 'Remote url for chapters file',
'chapters_file_delete' => 'Delete chapters file',
'advanced_section_title' => 'Advanced Parameters',
'advanced_section_subtitle' =>
'If you need RSS tags that Castopod does not handle, set them here.',
'custom_rss' => 'Custom RSS tags for the episode',
'custom_rss_hint' => 'This will be injected within the ❬item❭ tag.',
'block' => 'Episode should be hidden from all platforms',
'block_hint' =>
'The episode show or hide post. If you want this episode removed from the Apple directory, toggle this on.',
'submit_create' => 'Create episode',
'submit_edit' => 'Save episode',
],
'publish_form' => [
'back_to_episode_dashboard' => 'Back to episode dashboard',
'post' => 'Your announcement post',
'post_hint' =>
"Write a message to announce the publication of your episode. The message will be broadcasted to all your followers in the fediverse and be featured in your podcast's homepage.",
'publication_date' => 'Publication date',
'publication_method' => [
'now' => 'Now',
'schedule' => 'Schedule',
],
'scheduled_publication_date' => 'Scheduled publication date',
'scheduled_publication_date_clear' => 'Clear publication date',
'scheduled_publication_date_hint' =>
'You can schedule the episode release by setting a future publication date. This field must be formatted as YYYY-MM-DD HH:mm',
'submit' => 'Publish',
'submit_edit' => 'Edit publication',
'cancel_publication' => 'Cancel publication',
'message_warning' => 'You did not write a message for your announcement post!',
'message_warning_hint' => 'Having a message increases social engagement, resulting in a better visibility for your episode.',
'message_warning_submit' => 'Publish anyways',
],
'unpublish_form' => [
'disclaimer' =>
"Unpublishing the episode will delete all the notes associated with the episode and remove it from the podcast's RSS feed.",
'understand' => 'I understand, I want to unpublish the episode',
'submit' => 'Unpublish',
],
'soundbites' => 'Soundbites',
'soundbites_form' => [
'title' => 'Edit soundbites',
'info_section_title' => 'Episode soundbites',
'info_section_subtitle' => 'Add, edit or delete soundbites',
'start_time' => 'Start',
'start_time_hint' =>
'The first second of the soundbite, it can be a decimal number.',
'duration' => 'Duration',
'duration_hint' =>
'The duration of the soundbite (in seconds), it can be a decimal number.',
'label' => 'Label',
'label_hint' => 'Text that will be displayed.',
'play' => 'Play soundbite',
'delete' => 'Delete soundbite',
'bookmark' =>
'Click while playing to get current position, click again to get duration.',
'submit_edit' => 'Save all soundbites',
],
'embeddable_player' => [
'add' => 'Add embeddable player',
'title' => 'Embeddable player',
'label' =>
'Pick a theme color, copy the embeddable player to clipboard, then paste it on your website.',
'clipboard_iframe' => 'Copy embeddable player to clipboard',
'clipboard_url' => 'Copy address to clipboard',
'dark' => 'Dark',
'dark-transparent' => 'Dark transparent',
'light' => 'Light',
'light-transparent' => 'Light transparent',
],
];

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'blocked_actors' => 'Blocked accounts',
'blocked_domains' => 'Blocked domains',
'block_lists_form' => [
'handle' => 'Account handle',
'handle_hint' => 'Input @username@domain account.',
'domain' => 'Domain name',
'submit' => 'Block!',
],
'list' => [
'actor' => 'Account',
'domain' => 'Domain name',
'unblock' => 'Unblock',
],
];

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'all_podcasts' => 'All podcasts',
'no_podcast' => 'No podcast found',
];

View File

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'manual_config' => 'Manual configuration',
'manual_config_subtitle' =>
'Create a `.env` file with your settings and refresh the page to continue installation.',
'form' => [
'instance_config' => 'Instance configuration',
'hostname' => 'Hostname',
'media_base_url' => 'Media base URL',
'media_base_url_hint' =>
'If you use a CDN and/or an external analytics service, you may set them here.',
'admin_gateway' => 'Admin gateway',
'admin_gateway_hint' =>
'The route to access the admin area (eg. https://example.com/cp-admin). It is set by default as cp-admin, we recommend you change it for security reasons.',
'auth_gateway' => 'Auth gateway',
'auth_gateway_hint' =>
'The route to access the authentication pages (eg. https://example.com/cp-auth). It is set by default as cp-auth, we recommend you change it for security reasons.',
'database_config' => 'Database configuration',
'database_config_hint' =>
'Castopod needs to connect to your MySQL (or MariaDB) database. If you do not have these required info, please contact your server administrator.',
'db_hostname' => 'Database hostname',
'db_name' => 'Database name',
'db_username' => 'Database username',
'db_password' => 'Database password',
'db_prefix' => 'Database prefix',
'db_prefix_hint' =>
"The prefix of the Castopod table names, leave as is if you don't know what it means.",
'cache_config' => 'Cache configuration',
'cache_config_hint' =>
'Choose your preferred cache handler. Leave it as the default value if you have no clue what it means.',
'cache_handler' => 'Cache handler',
'cacheHandlerOptions' => [
'file' => 'File',
'redis' => 'Redis',
'predis' => 'Predis',
],
'next' => 'Next',
'submit' => 'Finish install',
'create_superadmin' => 'Create your superadmin account',
'email' => 'Email',
'username' => 'Username',
'password' => 'Password',
],
'messages' => [
'createSuperAdminSuccess' =>
'Your superadmin account has been created successfully. Login to start podcasting!',
'databaseConnectError' =>
'Castopod could not connect to your database. Edit your database configuration and try again.',
'writeError' =>
"Couldn't create/write the `.env` file. You must create it manually by following the `.env.example` file template in the Castopod package.",
],
];

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'info' => 'My account info',
'changePassword' => 'Change my password',
'messages' => [
'wrongPasswordError' => "You've entered the wrong password, try again.",
'passwordChangeSuccess' => 'Password has been successfully changed!',
],
];

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'go_to_website' => 'Go to website',
'dashboard' => 'Dashboard',
'admin' => 'Home',
'podcasts' => 'Podcasts',
'podcast-list' => 'All podcasts',
'podcast-create' => 'New podcast',
'podcast-import' => 'Import a podcast',
'persons' => 'Persons',
'person-list' => 'All persons',
'person-create' => 'New person',
'fediverse' => 'Fediverse',
'fediverse-blocked-actors' => 'Blocked accounts',
'fediverse-blocked-domains' => 'Blocked domains',
'users' => 'Users',
'user-list' => 'All users',
'user-create' => 'New user',
'pages' => 'Pages',
'page-list' => 'All pages',
'page-create' => 'New Page',
'account' => [
'my-account' => 'My account',
'change-password' => 'Change password',
'logout' => 'Logout',
],
];

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'back_to_home' => 'Back to home',
'page' => 'Page',
'all_pages' => 'All pages',
'create' => 'New page',
'go_to_page' => 'Go to page',
'edit' => 'Edit page',
'delete' => 'Delete page',
'form' => [
'title' => 'Title',
'permalink' => 'Permalink',
'content' => 'Content',
'submit_create' => 'Create page',
'submit_edit' => 'Save',
],
'messages' => [
'createSuccess' => 'The page “{pageTitle}” was created successfully!',
],
];

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'pageNavigation' => 'Page navigation',
'first' => 'First',
'previous' => 'Previous',
'next' => 'Next',
'last' => 'Last',
'older' => 'Older',
'newer' => 'Newer',
'invalidTemplate' => '{0} is not a valid Pager template.',
'invalidPaginationGroup' => '{0} is not a valid Pagination group.',
];

View File

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'persons' => 'Persons',
'all_persons' => 'All persons',
'no_person' => 'Nobody found!',
'create' => 'Create a person',
'view' => 'View person',
'edit' => 'Edit person',
'delete' => 'Delete person',
'form' => [
'identity_section_title' => 'Identity',
'identity_section_subtitle' => 'Who is working on the podcast',
'image' => 'Picture',
'image_size_hint' =>
'Image must be squared with at least 400px wide and tall.',
'full_name' => 'Full name',
'full_name_hint' => 'This is the full name or alias of the person.',
'unique_name' => 'Unique name',
'unique_name_hint' => 'Used for URLs',
'information_url' => 'Information URL',
'information_url_hint' =>
'Url to a relevant resource of information about the person, such as a homepage or third-party profile platform.',
'submit_create' => 'Create person',
'submit_edit' => 'Save person',
],
'podcast_form' => [
'title' => 'Manage persons',
'manage_section_title' => 'Management',
'manage_section_subtitle' => 'Remove persons from this podcast',
'add_section_title' => 'Add persons to this podcast',
'add_section_subtitle' => 'You may pick several persons and roles.',
'persons' => 'Persons',
'persons_hint' =>
'You may select one or several persons with the same roles. You need to create the persons first.',
'roles' => 'Roles',
'roles_hint' =>
'You may select none, one or several roles for a person.',
'submit_add' => 'Add person(s)',
'remove' => 'Remove',
],
'episode_form' => [
'title' => 'Manage persons',
'manage_section_title' => 'Management',
'manage_section_subtitle' => 'Remove persons from this episode',
'add_section_title' => 'Add persons to this episode',
'add_section_subtitle' => 'You may pick several persons and roles.',
'persons' => 'Persons',
'persons_hint' =>
'You may select one or several persons with the same roles. You need to create the persons first.',
'roles' => 'Roles',
'roles_hint' =>
'You may select none, one or several roles for a person.',
'submit_add' => 'Add person(s)',
'remove' => 'Remove',
],
'credits' => 'Credits',
];

View File

@ -1,470 +0,0 @@
<?php
/**
* @copyright 2021 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://podlibre.org/
*/
/* Autogenerated from https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-en.json on 2021-09-06T09:10:53+00:00 */
return array (
'persons' =>
array (
'creative_direction' =>
array (
'label' => 'Creative Direction',
'roles' =>
array (
'director' =>
array (
'label' => 'Director',
'description' => 'The Director is the head of the entire creative production, from creative details to logistics. There is typically a single director for a production. This role is primarily seen in fiction podcasts.',
'example' => 'Jenna Knorr for "Welcome to Tinsel Town"',
),
'assistant_director' =>
array (
'label' => 'Assistant Director',
'description' => 'The Assistant Director is a liaison between the director and the rest of the production, often coordinating the daily logistics of production. There may be multiple assistant directors on a project. This role is primarily seen in fiction podcasts.',
'example' => 'William Wright for "Inn Between"',
),
'executive_producer' =>
array (
'label' => 'Executive Producer',
'description' => 'The Executive Producer is the lead producer on a production. The role can range in terms of creative control with some "EP"s owning the creative direction of a podcast (in effect taking the role of director), while others may take a more hands off approach. Executive producer may have raised the money to fund the production, but it is not a necessary responsibility of the role.',
'example' => 'Jane Rotonda for "The Larry Meiller Show',
),
'senior_producer' =>
array (
'label' => 'Senior Producer',
'description' => 'The Senior Producer is the second most senior producer of the production (second to the Executive Producer). They supervise producers and the general direciton and logistics of the entire production.',
'example' => 'Dr. Jeremy Weisz from "INspired INsider"',
),
'producer' =>
array (
'label' => 'Producer',
'description' => 'The Producer coordinates and executes the production of the podcast. There duties can include helping craft the creative direction of a project, budgeting, research, scheduling, and overseeing editing and final production.',
'example' => '',
),
'associate_producer' =>
array (
'label' => 'Associate Producer',
'description' => 'The Associate Producer performs one or more producer functions as delegated to them by a Producer.',
'example' => 'Alex Baumhardt for "APM Reports"',
),
'development_producer' =>
array (
'label' => 'Development Producer',
'description' => 'The Development Producer coordinates and executes the pre-production create direction of a podcast. Their responsibilities include finding new episode and series ideas and working with writers and researchers to prepare the concept for production.',
'example' => '',
),
'creative_director' =>
array (
'label' => 'Creative Director',
'description' => 'The Creative Director is responsible for the creative strategy and execution of an entire series. Often this role reaches outside of content to affect accompanying artwork, music, marketing campaigns, and more.',
'example' => 'Neil Druckmann on "The Official The Last of Us"',
),
),
),
'cast' =>
array (
'label' => 'Cast',
'roles' =>
array (
'host' =>
array (
'label' => 'Host',
'description' => 'The Host is the on-air master of ceremonies of the podcast and a consistent presence on every episode (with the exception of guest hosts and alternative episodes). The Host\'s duties may include conducting interviews, introducing stories and segments, narrating, and more. There may be more than one Host per podcast or episode.',
'example' => 'Joe Rogan for "The Joe Rogan Experience"',
),
'co_host' =>
array (
'label' => 'Co-Host',
'description' => 'The Co-Host performs many of the same duties as the host, while taking a secondary presence on the podcast.',
'example' => 'Dax Shepard for "Armchair Expert"',
),
'guest_host' =>
array (
'label' => 'Guest Host',
'description' => 'The Guest Host performs all of the duties of the traditional Host role, but does so in a temporary capacity. Often as a single appearance or a short span of episodes.',
'example' => 'Erica Kelly on "Let\'s Taco \'Bout Women and True Crime"',
),
'guest' =>
array (
'label' => 'Guest',
'description' => 'The Guest is an outside party who makes an on-air appearance on an episode, often as a participant in a panel or the interview subject.',
'example' => 'Lewis Brindley for "Triforce!"',
),
'voice_actor' =>
array (
'label' => 'Voice Actor',
'description' => 'The Voice Actor gives a performance in which they lend their voice to the role of a character on a podcast episode. While the majority of voice acting roles will be fictional, the role of voice actor may also cover reenactments of real conversations and people.',
'example' => 'Venk Potula for "Masala Jones"',
),
'narrator' =>
array (
'label' => 'Narrator',
'description' => 'The Narrator gives a performance in which tell the exposition of a fictional or non-fictional story, often in a scripted manner. The Narrator may also perform voices of characters within the story, provided they still maintain the role of exposition storyteller or "voice of God".',
'example' => 'James Harvey Freetly for "Lakeshore & Limbo"',
),
'announcer' =>
array (
'label' => 'Announcer',
'description' => 'The Announcer gives short vocal performances for the introduction of the podcast, episode topics, segments, guests, prizes, etc. The Announcer is secondary to the host of the podcast and often performs their introductions in a scripted, produced manner.',
'example' => 'Lydia Kapp for "World Builders Anonymous"',
),
'reporter' =>
array (
'label' => 'Reporter',
'description' => 'The Reporter finds and investigates news or stories for the podcast, often interviewing subjects and conducting research. The Reporter can be an on-air position as well, as they convey the insights of their investigation.',
'example' => '',
),
),
),
'writing' =>
array (
'label' => 'Writing',
'roles' =>
array (
'author' =>
array (
'label' => 'Author',
'description' => 'The Author has written prose or poetry originally intended for text that is now being read verbatim on air.',
'example' => 'Heiko Martens for "The Sigmund Freud Files"',
),
'editorial_director' =>
array (
'label' => 'Editorial Director',
'description' => 'The Editorial Director heads all departments of the organization behind the podcast and is held accountable for delegating tasks to staff members and managing them. They are the highest-ranking editor and are responsible for the direction, accuracy, and decisions behind podcast content.',
'example' => 'Christopher Twarowski for "News Beat"',
),
'co_writer' =>
array (
'label' => 'Co-Writer',
'description' => 'The Co-Writer has written a podcast in partnership with 1-2 other writers, sharing credit together for the creative arc, dialogue, and narration.',
'example' => 'Max Eggers on "THE LIGHTHOUSE"',
),
'writer' =>
array (
'label' => 'Writer',
'description' => 'The Writer has written the story or dialogue of a podcast. The Writer is often involved in the creative arc of a production, but this is not a necessary requirement. Writers may work in fictional or non-fictional podcasts.',
'example' => '',
),
'songwriter' =>
array (
'label' => 'Songwriter',
'description' => 'The Songwriter has written the lyrics and/or accompanying music to an original song created for the podcast and played on an episode.',
'example' => 'Ben Lapidus for "Gay Future"',
),
'guest_writer' =>
array (
'label' => 'Guest Writer',
'description' => 'The Guest Writer performs the duties of a writer in a temporary capacity, often as a single episode or a short span of episodes. The distinction between writer and Guest Writer depends on the decision of the podcast itself.',
'example' => 'Beth Crane for "The Unseen Hour"',
),
'story_editor' =>
array (
'label' => 'Story Editor',
'description' => 'The Story Editor is responsible for broad stroke direction of the story arc and character development of a podcast. Often seen in fiction and documentary podcasts.',
'example' => 'Gabrielle Loux for "The NoSleep Podcast"',
),
'managing_editor' =>
array (
'label' => 'Managing Editor',
'description' => 'The Managing Editor oversees and coordinates the podcasts editorial activities, providing both detailed editing and managing a staff of writers and editors to ensure proper deadlines and budgets are being met.',
'example' => 'Flora Lichtman for "Every Little Thing"',
),
'script_editor' =>
array (
'label' => 'Script Editor',
'description' => 'The Script Editor provides notes and editing to the recording script in a very "hands on" role. The Script Editor is primarily used in fiction, documentary, and advertisements where scripted recordings are prevalent.',
'example' => 'Alex Rioux for "Welcome to Tinsel Town: A Christmas Adventure"',
),
'script_coordinator' =>
array (
'label' => 'Script Coordinator',
'description' => 'The Script Coordinator packages the final script with annotations that reflect specific logistics and creative cues for recording and production.',
'example' => 'Alex Rioux for "Welcome to Tinsel Town: A Christmas Adventure"',
),
'researcher' =>
array (
'label' => 'Researcher',
'description' => 'The Researcher coordinates the sourcing and verification of information that can then be used for the content of a podcast episode, often informing the direction of a story based on new insights uncovered.',
'example' => 'Dave Grave for "The Zero Brain Podcast"',
),
'editor' =>
array (
'label' => 'Editor',
'description' => 'The Editor reviews and prepares scripts for conveying information in a creative, accurate, and engaging manner.',
'example' => '',
),
'fact_checker' =>
array (
'label' => 'Fact Checker',
'description' => 'The Fact Checker reviews the content of a podcast for factual correctness and verifies that quote attribution is correct. They use a variety of tools including 3rd party research and individual outreach. Often the Fact Checker will also provide notes on how the production can avoid the confusion in the delivery of information in the episode.',
'example' => '',
),
'translator' =>
array (
'label' => 'Translator',
'description' => 'The Translator converts content from one language to another for the podcast. This can be interviews, dialogue, text documents, and more. The Translator\'s work may be used on-air or behind-the-scenes during the production/research process.',
'example' => '',
),
'transcriber' =>
array (
'label' => 'Transcriber',
'description' => 'The Transcriber turns dialogue and audio cues into text, which can be used internally for production processes or displayed publicly for listeners.',
'example' => '',
),
'logger' =>
array (
'label' => 'Logger',
'description' => 'The Logger reviews and documents the contents and timestamps of raw audio in service of producers and editors in the production process.',
'example' => '',
),
),
),
'audio_production' =>
array (
'label' => 'Audio Production',
'roles' =>
array (
'studio_coordinator' =>
array (
'label' => 'Studio Coordinator',
'description' => 'The Studio Coordinator manages the recording studio and audio technicians working within the studio at the time of recording.',
'example' => '',
),
'technical_director' =>
array (
'label' => 'Technical Director',
'description' => 'The Technical Director oversees the podcast\'s recording and production as it is involved with audio technologies including hardware and software, and managing roles involved these areas.',
'example' => 'Adam Raymonda on "Celebuzz\'d"',
),
'technical_manager' =>
array (
'label' => 'Technical Manager',
'description' => 'The Technical Manager coordinates a team of audio engineers and studio staff, in the recording and production as it is involved with audio technologies including hardware and software.',
'example' => '',
),
'audio_engineer' =>
array (
'label' => 'Audio Engineer',
'description' => 'The Audio Engineer helps record and produce audio by setting up recording environments, monitoring recoding, and providing technical adjustments throughout. The Audio Engineer is present during the recording process, most often making adjustments in real time. The Audio Engineer may work with conversation, music, foley, or any other type of audio.',
'example' => 'Peter Leonard from "Startup Podcast"',
),
'remote_recording_engineer' =>
array (
'label' => 'Remote Recording Engineer',
'description' => 'The Remote Recording Engineer ensures the proper recording of conversations taking place in multiple locations across a phone line or internet connection. The Remote Recording Engineer evaluates the different recording set ups and attempts to reconcile them into a cohesive sound, while also monitoring the recording process to capture the best possible audio.',
'example' => '',
),
'post_production_engineer' =>
array (
'label' => 'Post Production Engineer',
'description' => 'The Post Production Engineer evaluates audio technologies and their application as it pertains to the final steps of production and publication.',
'example' => 'Dick Wound for "Queens Next Door"',
),
),
),
'audio_post_production' =>
array (
'label' => 'Audio Post-Production',
'roles' =>
array (
'audio_editor' =>
array (
'label' => 'Audio Editor',
'description' => 'The Audio Editor cuts and rearranges audio for clarity and storytelling purposes. The Audio Editor may also perform general audio processing and mastering.',
'example' => '',
),
'sound_designer' =>
array (
'label' => 'Sound Designer',
'description' => 'The Sound Designer creates and composes a variety of audio elements. These elements are mostly secondary to speech, but a Sound Designer may creatively edit/produce speech elements in an artist manner.',
'example' => '',
),
'foley_artist' =>
array (
'label' => 'Foley Artist',
'description' => 'The Foley Artist sound effects for a podcast and can do so both via physical recording and digital processing, or a combination of the two.',
'example' => '',
),
'composer' =>
array (
'label' => 'Composer',
'description' => 'The Composer writes an original musical piece (or multiple) that is played on the published episode. The Composer will also often be the performer of said musical piece.',
'example' => 'Marcus Thorne Bagala from "This American Life"',
),
'theme_music' =>
array (
'label' => 'Theme Music',
'description' => 'Theme Music is a musical piece that accompanies the podcast across multiple episodes, most often at the beginning of an episode. The Theme Music is used to introduce the podcast as a brand. This role is for the creator of the theme music.',
'example' => 'Mark Philips from "Startup Podcast"',
),
'music_production' =>
array (
'label' => 'Music Production',
'description' => 'The Music Production role helps creatively craft music in a role separate from the writing of said music. Music Production often involves creative decisions per the method in which music is recorded, the arrangement of instruments, the use of effects, and more.',
'example' => 'Storm Duper for "Faking Star Wars Radio"',
),
'music_contributor' =>
array (
'label' => 'Music Contributor',
'description' => 'The Music Contributor is the creator of music that was used for the podcast but not necessarily produced specifically for the podcast. Often a podcast will use an existing musical piece and credit the original creator.',
'example' => 'Bobby Lord from "Startup Podcast"',
),
),
),
'administration' =>
array (
'label' => 'Administration',
'roles' =>
array (
'production_coordinator' =>
array (
'label' => 'Production Coordinator',
'description' => 'The Production Coordinator is responsible for managing the logistics of the production process from recording to publication, including attaining the required permissions and permits, connecting the various production and recording teams, coordinating the creation of post-production metadata, budgeting, and more.',
'example' => 'Taneya Boyde on "Ready For Change?"',
),
'booking_coordinator' =>
array (
'label' => 'Booking Coordinator',
'description' => 'The Booking Coordinator is responsible for bringing on new guests for interviews, including sourcing guests, scheduling interviews, onboarding materials, and post-publication processes.',
'example' => 'Meryl Klemow for "Campfire Sht Show"',
),
'production_assistant' =>
array (
'label' => 'Production Assistant',
'description' => 'The Production Assistant helps support an executive member of a podcast (often a director or producer), helping prepare them in a variety of ways including scheduling, logistics, communications, and more.',
'example' => 'Wallace Mack for "The Nod"',
),
'content_manager' =>
array (
'label' => 'Content Manager',
'description' => 'The Content Manager is responsible for the distribution of a podcast\'s content within and outside of episode, including but not limited to clips, newsletters, images, cross-promotions, and more.',
'example' => 'Kenneth Lee Johnson II for "Malice Corp Smack Talk"',
),
'marketing_manager' =>
array (
'label' => 'Marketing Manager',
'description' => 'The Marketing Manager is responsibile for the promotion of a podcast\'s content through various awareness strategies such as social media campaigns, cultivating a web presence, managing public relations and communications strategies, and other creative techniques to acquire and retain listeners.',
'example' => '',
),
'sales_representative' =>
array (
'label' => 'Sales Representative',
'description' => 'The Sales Representative is responsible for monetization of podcast content through managing and selling advertising inventory.',
'example' => '',
),
'sales_manager' =>
array (
'label' => 'Sales Manager',
'description' => 'The Sales Manager is responsible for all aspects of podcast monetization such as overseeing Sales Representatives, managing advertising inventory, and devising monetization strategies through channels such as affiliate partnerships, merchandise, live events, and other revenue strategies.',
'example' => '',
),
),
),
'visuals' =>
array (
'label' => 'Visuals',
'roles' =>
array (
'graphic_designer' =>
array (
'label' => 'Graphic Designer',
'description' => 'The Graphic Designer is someone who has created any custom visuals to accompany the podcast in a variety of ways.',
'example' => 'Sky Knight for "The XP Billionaires"',
),
'cover_art_designer' =>
array (
'label' => 'Cover Art Designer',
'description' => 'The Cover Art Designer creates the displayed cover art of a podcast or episode. For clarity, cover art is the main image (almost always square in dimensions) accompanying the podcast in directories, while episode cover art is displayed in a similar manner at the episode level. This role may be a digital designer, artist, photographer or any other visual creative.',
'example' => '',
),
),
),
'community' =>
array (
'label' => 'Community',
'roles' =>
array (
'social_media_manager' =>
array (
'label' => 'Social Media Manager',
'description' => 'The Social Media Manager runs the social media accounts of the podcast, including but not limited to the creation of content, posting, replies, monitoring, and more.',
'example' => 'Tom Joshi-Cale for "World on a String"',
),
),
),
'misc' =>
array (
'label' => 'Misc.',
'roles' =>
array (
'consultant' =>
array (
'label' => 'Consultant',
'description' => 'A Consultant is a third-party position where someone from outside the organization works on a project, often offering a specific expertise. This is a modifier role and can be applied to any work area.',
'example' => 'Ross Wilcock for "Being Kenzie-Feature Length Immersive Horror"',
),
'intern' =>
array (
'label' => 'Intern',
'description' => 'An Intern is an apprentice position where someone works for a limited time within an organization to gain work experience in a specific field. This is a modifier role and can be applied to any work area.',
'example' => '',
),
),
),
'video_production' =>
array (
'label' => 'Video Production',
'roles' =>
array (
'camera_operator' =>
array (
'label' => 'Camera Operator',
'description' => 'A camera operator is responsible for capturing and recording all aspects of a scene for film and television. They must understand the technicalities of how to operate a camera, frame a proper shot with respect to lighting and staging, focus the lens and have a visual eye to achieve a specific look.',
'example' => '',
),
'lighting_designer' =>
array (
'label' => 'Lighting Designer',
'description' => 'A lighting designer works with the DP and Director to craft a specific look and feel of a scene utilizing various lighting techniques. They must be able to interpret the creative direction and bring it to life.',
'example' => '',
),
'camera_grip' =>
array (
'label' => 'Camera Grip',
'description' => 'A camera grip is responsible for building and maintaining all the parts of a camera and its accessories such as the tripods, cranes, dollies, etc.',
'example' => '',
),
'assistant_camera' =>
array (
'label' => 'Assistant Camera',
'description' => '1st AC is responsible for the camera equipment, building the cameras before the start of each day, organizing all the parts and various accessories, swapping out lenses when necessary and also pulls focus for the DP and camera operators. The AC will also wrap out each day by cleaning the cameras, writing camera notes, marking the media cards, and delivering them to the DIT.',
'example' => '',
),
),
),
'video_post_production' =>
array (
'label' => 'Video Post-Production',
'roles' =>
array (
'editor' =>
array (
'label' => 'Editor',
'description' => 'Television editors are responsible for taking the shot footage and clips and blending them together to craft the director\'s vision and storytelling.',
'example' => '',
),
'assistant_editor' =>
array (
'label' => 'Assistant Editor',
'description' => 'The Assistant Editor is responsible for taking the media from the set, ingesting them into the designated editing software, and organizing the footage in an efficient way for the editor. They must also pay close attention to ensure that audio and video are synced and that all footage from set is ingested properly.',
'example' => '',
),
),
),
),
);

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'title' => 'Platforms',
'home_url' => 'Go to {platformName} website',
'submit_url' => 'Submit your podcast on {platformName}',
'visible' => 'Display in podcast homepage?',
'on_embeddable_player' => 'Display on embeddable player?',
'remove' => 'Remove {platformName}',
'submit' => 'Save',
'messages' => [
'updateSuccess' => 'Platform links have been successfully updated!',
'removeLinkSuccess' => 'The platform link has been removed.',
'removeLinkError' =>
'The platform link could not be removed. Try again.',
],
'description' => [
'podcasting' => 'The podcast ID on this platform',
'social' => 'The podcast account ID on this platform',
'funding' => 'Call to action message',
],
];

View File

@ -0,0 +1,237 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'all_podcasts' => 'All podcasts',
'no_podcast' => 'No podcast found!',
'create' => 'Create a podcast',
'import' => 'Import a podcast',
'new_episode' => 'New Episode',
'feed' => 'RSS',
'view' => 'View podcast',
'edit' => 'Edit podcast',
'delete' => 'Delete podcast',
'see_episodes' => 'See episodes',
'see_contributors' => 'See contributors',
'go_to_page' => 'Go to page',
'latest_episodes' => 'Latest episodes',
'see_all_episodes' => 'See all episodes',
'form' => [
'identity_section_title' => 'Podcast identity',
'identity_section_subtitle' => 'These fields allow you to get noticed.',
'image' => 'Cover image',
'title' => 'Title',
'handle' => 'Handle',
'handle_hint' =>
'Used to identify the podcast. Uppercase, lowercase, numbers and underscores are accepted.',
'type' => [
'label' => 'Type',
'hint' =>
'- <strong>episodic</strong>: if episodes are intended to be consumed without any specific order. Newest episodes will be presented first.<br/>- <strong>serial</strong>: if episodes are intended to be consumed in sequential order. The oldest episodes will be presented first.',
'episodic' => 'Episodic',
'serial' => 'Serial',
],
'description' => 'Description',
'classification_section_title' => 'Classification',
'classification_section_subtitle' =>
'These fields will impact your audience and competition.',
'language' => 'Language',
'category' => 'Category',
'category_placeholder' => 'Select a category…',
'other_categories' => 'Other categories',
'parental_advisory' => [
'label' => 'Parental advisory',
'hint' => 'Does it contain explicit content?',
'undefined' => 'undefined',
'clean' => 'Clean',
'explicit' => 'Explicit',
],
'author_section_title' => 'Author',
'author_section_subtitle' => 'Who is managing the podcast?',
'owner_name' => 'Owner name',
'owner_name_hint' =>
'For administrative use only. Visible in the public RSS feed.',
'owner_email' => 'Owner email',
'owner_email_hint' =>
'Will be used by most platforms to verify the podcast ownership. Visible in the public RSS feed.',
'publisher' => 'Publisher',
'publisher_hint' =>
'The group responsible for creating the show. Often refers to the parent company or network of a podcast. This field is sometimes labeled as Author.',
'copyright' => 'Copyright',
'location_section_title' => 'Location',
'location_section_subtitle' => 'What place is this podcast about?',
'location_name' => 'Location name or address',
'location_name_hint' => 'This can be a real place or fictional',
'monetization_section_title' => 'Monetization',
'monetization_section_subtitle' =>
'Earn money thanks to your audience.',
'payment_pointer' => 'Payment Pointer for Web Monetization',
'payment_pointer_hint' =>
'This is your where you will receive money thanks to Web Monetization',
'advanced_section_title' => 'Advanced Parameters',
'advanced_section_subtitle' =>
'If you need RSS tags that Castopod does not handle, set them here.',
'custom_rss' => 'Custom RSS tags for the podcast',
'custom_rss_hint' => 'This will be injected within the ❬channel❭ tag.',
'partnership' => 'Partnership',
'partner_id' => 'ID',
'partner_link_url' => 'Link URL',
'partner_image_url' => 'Image URL',
'partner_id_hint' => 'Your own partner ID',
'partner_link_url_hint' => 'The generic partner link address',
'partner_image_url_hint' => 'The generic partner image address',
'status_section_title' => 'Status',
'status_section_subtitle' => 'Dead or alive?',
'block' => 'Podcast should be hidden from all platforms',
'complete' => 'Podcast will not be having new episodes',
'lock' => 'Prevent podcast from being copied',
'lock_hint' =>
'The purpose is to tell other podcast platforms whether they are allowed to import this feed. A value of yes means that any attempt to import this feed into a new platform should be rejected.',
'submit_create' => 'Create podcast',
'submit_edit' => 'Save podcast',
],
'category_options' => [
'uncategorized' => 'uncategorized',
'arts' => 'Arts',
'business' => 'Business',
'comedy' => 'Comedy',
'education' => 'Education',
'fiction' => 'Fiction',
'government' => 'Government',
'health_and_fitness' => 'Health &amp Fitness',
'history' => 'History',
'kids_and_family' => 'Kids &amp Family',
'leisure' => 'Leisure',
'music' => 'Music',
'news' => 'News',
'religion_and_spirituality' => 'Religion &amp Spirituality',
'science' => 'Science',
'society_and_culture' => 'Society &amp Culture',
'sports' => 'Sports',
'technology' => 'Technology',
'true_crime' => 'True Crime',
'tv_and_film' => 'TV &amp Film',
'books' => 'Books',
'design' => 'Design',
'fashion_and_beauty' => 'Fashion &amp Beauty',
'food' => 'Food',
'performing_arts' => 'Performing Arts',
'visual_arts' => 'Visual Arts',
'careers' => 'Careers',
'entrepreneurship' => 'Entrepreneurship',
'investing' => 'Investing',
'management' => 'Management',
'marketing' => 'Marketing',
'non_profit' => 'Non-Profit',
'comedy_interviews' => 'Comedy Interviews',
'improv' => 'Improv',
'stand_up' => 'Stand-Up',
'courses' => 'Courses',
'how_to' => 'How To',
'language_learning' => 'Language Learning',
'self_improvement' => 'Self-Improvement',
'comedy_fiction' => 'Comedy Fiction',
'drama' => 'Drama',
'science_fiction' => 'Science Fiction',
'alternative_health' => 'Alternative Health',
'fitness' => 'Fitness',
'medicine' => 'Medicine',
'mental_health' => 'Mental Health',
'nutrition' => 'Nutrition',
'sexuality' => 'Sexuality',
'education_for_kids' => 'Education for Kids',
'parenting' => 'Parenting',
'pets_and_animals' => 'Pets &amp Animals',
'stories_for_kids' => 'Stories for Kids',
'animation_and_manga' => 'Animation &amp Manga',
'automotive' => 'Automotive',
'aviation' => 'Aviation',
'crafts' => 'Crafts',
'games' => 'Games',
'hobbies' => 'Hobbies',
'home_and_garden' => 'Home &amp Garden',
'video_games' => 'Video Games',
'music_commentary' => 'Music Commentary',
'music_history' => 'Music History',
'music_interviews' => 'Music Interviews',
'business_news' => 'Business News',
'daily_news' => 'Daily News',
'entertainment_news' => 'Entertainment News',
'news_commentary' => 'News Commentary',
'politics' => 'Politics',
'sports_news' => 'Sports News',
'tech_news' => 'Tech News',
'buddhism' => 'Buddhism',
'christianity' => 'Christianity',
'hinduism' => 'Hinduism',
'islam' => 'Islam',
'judaism' => 'Judaism',
'religion' => 'Religion',
'spirituality' => 'Spirituality',
'astronomy' => 'Astronomy',
'chemistry' => 'Chemistry',
'earth_sciences' => 'Earth Sciences',
'life_sciences' => 'Life Sciences',
'mathematics' => 'Mathematics',
'natural_sciences' => 'Natural Sciences',
'nature' => 'Nature',
'physics' => 'Physics',
'social_sciences' => 'Social Sciences',
'documentary' => 'Documentary',
'personal_journals' => 'Personal Journals',
'philosophy' => 'Philosophy',
'places_and_travel' => 'Places &amp Travel',
'relationships' => 'Relationships',
'baseball' => 'Baseball',
'basketball' => 'Basketball',
'cricket' => 'Cricket',
'fantasy_sports' => 'Fantasy Sports',
'football' => 'Football',
'golf' => 'Golf',
'hockey' => 'Hockey',
'rugby' => 'Rugby',
'running' => 'Running',
'soccer' => 'Soccer',
'swimming' => 'Swimming',
'tennis' => 'Tennis',
'volleyball' => 'Volleyball',
'wilderness' => 'Wilderness',
'wrestling' => 'Wrestling',
'after_shows' => 'After Shows',
'film_history' => 'Film History',
'film_interviews' => 'Film Interviews',
'film_reviews' => 'Film Reviews',
'tv_reviews' => 'TV Reviews',
],
'by' => 'By {publisher}',
'season' => 'Season {seasonNumber}',
'list_of_episodes_year' => '{year} episodes ({episodeCount})',
'list_of_episodes_season' =>
'Season {seasonNumber} episodes ({episodeCount})',
'no_episode' => 'No episode found!',
'no_episode_hint' =>
'Navigate the podcast episodes with the navigation bar above.',
'follow' => 'Follow',
'followers' => '{numberOfFollowers, plural,
one {<span class="font-semibold">#</span> follower}
other {<span class="font-semibold">#</span> followers}
}',
'posts' => '{numberOfPosts, plural,
one {<span class="font-semibold">#</span> post}
other {<span class="font-semibold">#</span> posts}
}',
'activity' => 'Activity',
'episodes' => 'Episodes',
'sponsor_title' => 'Enjoying the show?',
'sponsor' => 'Sponsor',
'funding_links' => 'Funding links for {podcastTitle}',
'find_on' => 'Find {podcastTitle} on',
'listen_on' => 'Listen on',
];

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'warning' =>
'This procedure may take a long time.<br/>As the current version does not show any progress while it runs, you will not see anything updated until it is done.<br/>In case of timeout error, increase `max_execution_time` value.',
'old_podcast_section_title' => 'The podcast to import',
'old_podcast_section_subtitle' =>
'Make sure you own the rights for this podcast before importing it. Copying and broadcasting a podcast without the proper rights is piracy and is liable to prosecution.',
'imported_feed_url' => 'Feed URL',
'imported_feed_url_hint' => 'The feed must be in xml or rss format.',
'new_podcast_section_title' => 'The new podcast',
'advanced_params_section_title' => 'Advanced parameters',
'advanced_params_section_subtitle' =>
'Keep the default values if you have no idea of what the fields are for.',
'slug_field' => [
'label' => 'Which field should be used to calculate episode slug',
'link' => '&lt;link&gt;',
'title' => '&lt;title&gt;',
],
'description_field' =>
'Source field used for episode description / show notes',
'force_renumber' => 'Force episodes renumbering',
'force_renumber_hint' =>
'Use this if your podcast does not have episode numbers but wish to set them during import.',
'season_number' => 'Season number',
'season_number_hint' =>
'Use this if your podcast does not have a season number but wish to set one during import. Leave blank otherwise.',
'max_episodes' => 'Maximum number of episodes to import',
'max_episodes_hint' => 'Leave blank to import all episodes',
'lock_import' =>
'This feed is protected. You cannot import it. If you are the owner, unprotect it on the origin platform.',
'submit' => 'Import podcast',
];

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'go_to_page' => 'Go to podcast page',
'dashboard' => 'Podcast dashboard',
'podcast-view' => 'Home',
'podcast-edit' => 'Edit podcast',
'episodes' => 'Episodes',
'episode-list' => 'All episodes',
'episode-create' => 'New episode',
'fediverse' => 'Fediverse',
'fediverse-block_lists' => 'Block lists',
'analytics' => 'Analytics',
'persons' => 'Persons',
'podcast-person-manage' => 'Manage persons',
'contributors' => 'Contributors',
'contributor-list' => 'All contributors',
'contributor-add' => 'Add contributor',
'platforms' => 'External platforms',
'platforms-podcasting' => 'Podcasting',
'platforms-social' => 'Social Networks',
'platforms-funding' => 'Funding',
'podcast-analytics' => 'Audience overview',
'podcast-analytics-webpages' => 'Web pages visits',
'podcast-analytics-locations' => 'Locations',
'podcast-analytics-unique-listeners' => 'Unique listeners',
'podcast-analytics-players' => 'Players',
'podcast-analytics-listening-time' => 'Listening time',
'podcast-analytics-time-periods' => 'Time periods',
];

View File

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'edit_roles' => "Edit {username}'s roles",
'forcePassReset' => 'Force pass reset',
'ban' => 'Ban',
'unban' => 'Unban',
'delete' => 'Delete',
'create' => 'New user',
'view' => "{username}'s info",
'all_users' => 'All users',
'list' => [
'user' => 'User',
'roles' => 'Roles',
'banned' => 'Banned?',
],
'form' => [
'email' => 'Email',
'username' => 'Username',
'password' => 'Password',
'new_password' => 'New Password',
'roles' => 'Roles',
'permissions' => 'Permissions',
'submit_create' => 'Create user',
'submit_edit' => 'Save',
'submit_password_change' => 'Change!',
],
'roles' => [
'superadmin' => 'Super admin',
],
'messages' => [
'createSuccess' =>
'User created successfully! {username} will be prompted with a password reset upon first authentication.',
'rolesEditSuccess' =>
"{username}'s roles have been successfully updated.",
'forcePassResetSuccess' =>
'{username} will be prompted with a password reset upon next visit.',
'banSuccess' => '{username} has been banned.',
'unbanSuccess' => '{username} has been unbanned.',
'banSuperAdminError' =>
'{username} is a superadmin, one does not simply ban a superadmin…',
'deleteSuperAdminError' =>
'{username} is a superadmin, one does not simply delete a superadmin…',
'deleteSuccess' => '{username} has been deleted.',
],
];

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'min_dims' =>
'{field} is either not an image, or it is not wide or tall enough.',
'is_image_squared' =>
'{field} is either not an image, or it is not squared (width and height differ).',
'validate_url' =>
'The {field} field must be a valid URL (eg. https://example.com/).',
];

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'dashboard' => 'Tableau de bord',
'welcome_message' => 'Bienvenue dans ladministration!',
];

View File

@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'label' => 'Fil dAriane',
config('Admin')
->gateway => 'Accueil',
'podcasts' => 'podcasts',
'episodes' => 'épisodes',
'contributors' => 'contributeurs',
'pages' => 'pages',
'add' => 'ajouter',
'new' => 'créer',
'edit' => 'modifier',
'persons' => 'intervenants',
'publish' => 'publier',
'publish-edit' => 'modifier la publication',
'unpublish' => 'dépublier',
'fediverse' => 'fédiverse',
'block-lists' => 'listes de blocage',
'users' => 'utilisateurs',
'my-account' => 'mon compte',
'change-password' => 'changer le mot de passe',
'import' => 'importer un flux',
'platforms' => 'plateformes',
'social' => 'réseaux sociaux',
'funding' => 'financement',
'analytics' => 'mesures daudience',
'locations' => 'localisations',
'webpages' => 'pages web',
'unique-listeners' => 'auditeurs uniques',
'players' => 'lecteurs',
'listening-time' => 'drée découte',
'time-periods' => 'périodes',
'soundbites' => 'extraits sonores',
'embeddable-player' => 'lecteur intégré',
];

View File

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'by_service_weekly' =>
'Téléchargements dépisodes par service (sur la dernière semaine)',
'by_player_weekly' =>
'Téléchargements dépisodes par lecteur (sur la dernière semaine)',
'by_player_yearly' =>
'Téléchargements dépisodes par lecteur (sur la dernière année)',
'by_device_weekly' =>
'Téléchargements dépisodes par appareil (sur la dernière semaine)',
'by_os_weekly' =>
'Téléchargements dépisodes par OS (sur la dernière semaine)',
'podcast_by_region' =>
'Téléchargements dépisodes par région (sur la dernière semaine)',
'unique_daily_listeners' => 'Auditeurs uniques quotidiens',
'unique_monthly_listeners' => 'Auditeurs uniques mensuels',
'by_browser' =>
'Fréquentation des pages web par navigateur (sur la dernière semaine)',
'podcast_by_day' => 'Téléchargements quotidiens dépisodes',
'podcast_by_month' => 'Téléchargements mensuels dépisodes',
'episode_by_day' =>
'Téléchargements quotidiens de lépisode (sur les 60 premiers jours)',
'episode_by_month' => 'Téléchargements mensuels de lépisode',
'episodes_by_day' =>
'Téléchargements des 5 derniers épisodes (sur les 60 premiers jours)',
'by_country_weekly' =>
'Téléchargement dépisodes par pays (sur la dernière semaine)',
'by_country_yearly' =>
'Téléchargement dépisodes par pays (sur la dernière année)',
'by_domain_weekly' =>
'Fréquentation des pages web par origine (sur la dernière semaine)',
'by_domain_yearly' =>
'Fréquentation des pages web par origine (sur la dernière année)',
'by_entry_page' =>
'Fréquentation des pages web par page dentrée (sur la dernière semaine)',
'podcast_bots' => 'Robots (bots)',
'daily_listening_time' => 'Durée quotidienne découte cumulée',
'monthly_listening_time' => 'Durée mensuelle découte cumulée',
'by_weekday' => 'Par jour de la semaine (sur les 60 derniers jours)',
'by_hour' => 'Par heure de la journée (sur les 60 derniers jours)',
'podcast_by_bandwidth' => 'Bande passante quotidienne consommée (en Mo)',
];

View File

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'yes' => 'Oui',
'no' => 'Non',
'cancel' => 'Annuler',
'optional' => 'Optionnel',
'more' => 'Plus',
'no_data' => 'Aucune donnée trouvée!',
'close' => 'Fermer',
'edit' => 'Modifier',
'copy' => 'Copier',
'copied' => 'Copié!',
'home' => 'Accueil',
'explicit' => 'Explicite',
'mediumDate' => '{0,date,medium}',
'powered_by' => 'Propulsé par {castopod}.',
'actions' => 'Actions',
'pageInfo' => 'Page {currentPage} sur {pageCount}',
'go_back' => 'Retour en arrière',
'forms' => [
'editor' => [
'write' => 'Écrire',
'preview' => 'Aperçu',
'help' => 'Propulsé par markdown',
],
'multiSelect' => [
'selectText' => 'Cliquez pour selectionner',
'loadingText' => 'Chargement...',
'noResultsText' => 'Aucun résultat trouvé',
'noChoicesText' => 'Aucune sélection possible',
'maxItemText' => 'Impossible de rajouter un élément',
],
'image_size_hint' =>
'Limage doit être carrée, avec au minimum 1400px de long et de large.',
'upload_file' => 'Téléversez un fichier',
'remote_url' => 'URL distante',
],
'play_episode_button' => [
'play' => 'Lire',
'playing' => 'En cours',
],
];

View File

@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'podcast_contributors' => 'Contributeurs du podcast',
'view' => 'Contribution de {username} à {podcastTitle}',
'add' => 'Ajouter un contributeur',
'add_contributor' => 'Ajouter un contributeur pour {0}',
'edit_role' => 'Modifier le rôle de {0}',
'edit' => 'Modifier',
'remove' => 'Supprimer',
'list' => [
'username' => 'Identifiant',
'role' => 'Rôle',
],
'form' => [
'user' => 'Utilisateur',
'user_placeholder' => 'Sélectionnez un utilisateur…',
'role' => 'Rôle',
'role_placeholder' => 'Sélectionnez son rôle…',
'submit_add' => 'Ajouter le contributeur',
'submit_edit' => 'Mettre à jour le rôle',
],
'roles' => [
'podcast_admin' => 'Administrateur de Podcasts',
],
'messages' => [
'removeOwnerContributorError' =>
'Vous ne pouvez pas retirer le propriétaire du podcast!',
'removeContributorSuccess' =>
'Vous avez retiré {username} de {podcastTitle}',
'alreadyAddedError' =>
'Le contributeur que vous essayez dajouter est déjà présent.',
],
];

View File

@ -0,0 +1,264 @@
<?php
declare(strict_types=1);
/**
* ISO 3166 country codes
*
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'AF ' => 'Afghanistan',
'ZA ' => 'Afrique Du Sud',
'AX ' => 'Åland, Îles',
'AL ' => 'Albanie',
'DZ ' => 'Algérie',
'DE ' => 'Allemagne',
'AD ' => 'Andorre',
'AO ' => 'Angola',
'AI ' => 'Anguilla',
'AQ ' => 'Antarctique',
'AG ' => 'Antigua-Et-Barbuda',
'SA ' => 'Arabie Saoudite',
'AR ' => 'Argentine',
'AM ' => 'Arménie',
'AW ' => 'Aruba',
'AU ' => 'Australie',
'AT ' => 'Autriche',
'AZ ' => 'Azerbaïdjan',
'BS ' => 'Bahamas',
'BH ' => 'Bahreïn',
'BD ' => 'Bangladesh',
'BB ' => 'Barbade',
'BY ' => 'Bélarus',
'BE ' => 'Belgique',
'BZ ' => 'Belize',
'BJ ' => 'Bénin',
'BM ' => 'Bermudes',
'BT ' => 'Bhoutan',
'BO ' => 'Bolivie, État Plurinational De',
'BQ ' => 'Bonaire, Saint-Eustache Et Saba',
'BA ' => 'Bosnie-Herzégovine',
'BW ' => 'Botswana',
'BV ' => 'Bouvet, Île',
'BR ' => 'Brésil',
'BN ' => 'Brunéi Darussalam',
'BG ' => 'Bulgarie',
'BF ' => 'Burkina Faso',
'BI ' => 'Burundi',
'KY ' => 'Caïmanes, Îles',
'KH ' => 'Cambodge',
'CM ' => 'Cameroun',
'CA ' => 'Canada',
'CV ' => 'Cabo Verde',
'CF ' => 'Centrafricaine, République',
'CL ' => 'Chili',
'CN ' => 'Chine',
'CX ' => 'Christmas, Île',
'CY ' => 'Chypre',
'CC ' => 'Cocos (Keeling), Îles',
'CO ' => 'Colombie',
'KM ' => 'Comores',
'CG ' => 'Congo',
'CD ' => 'Congo, La République Démocratique Du',
'CK ' => 'Cook, Îles',
'KR ' => 'Corée, République De',
'KP ' => 'Corée, République Populaire Démocratique De',
'CR ' => 'Costa Rica',
'CI ' => 'Côte Divoire',
'HR ' => 'Croatie',
'CU ' => 'Cuba',
'CW ' => 'Curaçao',
'DK ' => 'Danemark',
'DJ ' => 'Djibouti',
'DO ' => 'Dominicaine, République',
'DM ' => 'Dominique',
'EG ' => 'Égypte',
'SV ' => 'El Salvador',
'AE ' => 'Émirats Arabes Unis',
'EC ' => 'Équateur',
'ER ' => 'Érythrée',
'ES ' => 'Espagne',
'EE ' => 'Estonie',
'US ' => 'États-Unis',
'ET ' => 'Éthiopie',
'FK ' => 'Falkland, Îles (Malvinas)',
'FO ' => 'Féroé, Îles',
'FJ ' => 'Fidji',
'FI ' => 'Finlande',
'FR ' => 'France',
'GA ' => 'Gabon',
'GM ' => 'Gambie',
'GE ' => 'Géorgie',
'GS ' => 'Géorgie Du Sud Et Les Îles Sandwich Du Sud',
'GH ' => 'Ghana',
'GI ' => 'Gibraltar',
'GR ' => 'Grèce',
'GD ' => 'Grenade',
'GL ' => 'Groenland',
'GP ' => 'Guadeloupe',
'GU ' => 'Guam',
'GT ' => 'Guatemala',
'GG ' => 'Guernesey',
'GN ' => 'Guinée',
'GW ' => 'Guinée-Bissau',
'GQ ' => 'Guinée Équatoriale',
'GY ' => 'Guyana',
'GF ' => 'Guyane Française',
'HT ' => 'Haïti',
'HM ' => 'Heard Et Macdonald, Îles',
'HN ' => 'Honduras',
'HK ' => 'Hong Kong',
'HU ' => 'Hongrie',
'IM ' => 'Île De Man',
'UM ' => 'Îles Mineures Éloignées Des États-Unis',
'VG ' => 'Îles Vierges Britanniques',
'VI ' => 'Îles Vierges Des États-Unis',
'IN ' => 'Inde',
'ID ' => 'Indonésie',
'IR ' => "Iran, République Islamique D'",
'IQ ' => 'Iraq',
'IE ' => 'Irlande',
'IS ' => 'Islande',
'IL ' => 'Israël',
'IT ' => 'Italie',
'JM ' => 'Jamaïque',
'JP ' => 'Japon',
'JE ' => 'Jersey',
'JO ' => 'Jordanie',
'KZ ' => 'Kazakhstan',
'KE ' => 'Kenya',
'KG ' => 'Kirghizistan',
'KI ' => 'Kiribati',
'KW ' => 'Koweït',
'LA ' => 'Lao, République Démocratique Populaire',
'LS ' => 'Lesotho',
'LV ' => 'Lettonie',
'LB ' => 'Liban',
'LR ' => 'Libéria',
'LY ' => 'Libye',
'LI ' => 'Liechtenstein',
'LT ' => 'Lituanie',
'LU ' => 'Luxembourg',
'MO ' => 'Macao',
'MK ' => 'République De Macédoine',
'MG ' => 'Madagascar',
'MY ' => 'Malaisie',
'MW ' => 'Malawi',
'MV ' => 'Maldives',
'ML ' => 'Mali',
'MT ' => 'Malte',
'MP ' => 'Mariannes Du Nord, Îles',
'MA ' => 'Maroc',
'MH ' => 'Marshall, Îles',
'MQ ' => 'Martinique',
'MU ' => 'Maurice',
'MR ' => 'Mauritanie',
'YT ' => 'Mayotte',
'MX ' => 'Mexique',
'FM ' => 'Micronésie, États Fédérés De',
'MD ' => 'Moldavie',
'MC ' => 'Monaco',
'MN ' => 'Mongolie',
'ME ' => 'Monténégro',
'MS ' => 'Montserrat',
'MZ ' => 'Mozambique',
'MM ' => 'Myanmar',
'NA ' => 'Namibie',
'N/A' => 'Non Applicable (IP locale…)',
'NR ' => 'Nauru',
'NP ' => 'Népal',
'NI ' => 'Nicaragua',
'NE ' => 'Niger',
'NG ' => 'Nigéria',
'NU ' => 'Niué',
'NF ' => 'Norfolk, Île',
'NO ' => 'Norvège',
'NC ' => 'Nouvelle-Calédonie',
'NZ ' => 'Nouvelle-Zélande',
'IO ' => "Océan Indien, Territoire Britannique De L'",
'OM ' => 'Oman',
'UG ' => 'Ouganda',
'UZ ' => 'Ouzbékistan',
'PK ' => 'Pakistan',
'PW ' => 'Palaos',
'PS ' => 'État De Palestine',
'PA ' => 'Panama',
'PG ' => 'Papouasie-Nouvelle-Guinée',
'PY ' => 'Paraguay',
'NL ' => 'Pays-Bas',
'PE ' => 'Pérou',
'PH ' => 'Philippines',
'PN ' => 'Pitcairn',
'PL ' => 'Pologne',
'PF ' => 'Polynésie Française',
'PR ' => 'Porto Rico',
'PT ' => 'Portugal',
'QA ' => 'Qatar',
'RE ' => 'Réunion',
'RO ' => 'Roumanie',
'GB ' => 'Royaume-Uni',
'RU ' => 'Russie, Fédération De',
'RW ' => 'Rwanda',
'EH ' => 'Sahara Occidental',
'BL ' => 'Saint-Barthélemy',
'KN ' => 'Saint-Kitts-Et-Nevis',
'SM ' => 'Saint-Marin',
'MF ' => 'Saint-Martin (Partie Française)',
'SX ' => 'Saint-Martin (Partie Néerlandaise)',
'PM ' => 'Saint-Pierre-Et-Miquelon',
'VA ' => 'Saint-Siège (État De La Cité Du Vatican)',
'VC ' => 'Saint-Vincent-Et-Les-Grenadines',
'SH ' => 'Sainte-Hélène, Ascension Et Tristan Da Cunha',
'LC ' => 'Sainte-Lucie',
'SB ' => 'Salomon, Îles',
'WS ' => 'Samoa',
'AS ' => 'Samoa Américaines',
'ST ' => 'Sao Tomé-Et-Principe',
'SN ' => 'Sénégal',
'RS ' => 'Serbie',
'SC ' => 'Seychelles',
'SL ' => 'Sierra Leone',
'SG ' => 'Singapour',
'SK ' => 'Slovaquie',
'SI ' => 'Slovénie',
'SO ' => 'Somalie',
'SD ' => 'Soudan',
'SS ' => 'Soudan Du Sud',
'LK ' => 'Sri Lanka',
'SE ' => 'Suède',
'CH ' => 'Suisse',
'SR ' => 'Suriname',
'SJ ' => 'Svalbard Et Île Jan Mayen',
'SZ ' => 'Eswatini',
'SY ' => 'Syrienne, République Arabe',
'TJ ' => 'Tadjikistan',
'TW ' => 'Taïwan, Province De Chine',
'TZ ' => 'Tanzanie, République Unie De',
'TD ' => 'Tchad',
'CZ ' => 'Tchéquie',
'TF ' => 'Terres Australes Françaises',
'TH ' => 'Thaïlande',
'TL ' => 'Timor-Leste',
'TG ' => 'Togo',
'TK ' => 'Tokelau',
'TO ' => 'Tonga',
'TT ' => 'Trinité-Et-Tobago',
'TN ' => 'Tunisie',
'TM ' => 'Turkménistan',
'TC ' => 'Turks Et Caïques, Îles',
'TR ' => 'Turquie',
'TV ' => 'Tuvalu',
'UA ' => 'Ukraine',
'UY ' => 'Uruguay',
'VU ' => 'Vanuatu',
'VE ' => 'Venezuela, République Bolivarienne Du',
'VN ' => 'Viet Nam',
'WF ' => 'Wallis-Et-Futuna',
'YE ' => 'Yémen',
'ZM ' => 'Zambie',
'ZW ' => 'Zimbabwe',
];

View File

@ -0,0 +1,175 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'season' => 'Saison {seasonNumber}',
'season_abbr' => 'S{seasonNumber}',
'number' => 'Épisode {episodeNumber}',
'number_abbr' => 'Ep. {episodeNumber}',
'season_episode' => 'Saison {seasonNumber} épisode {episodeNumber}',
'season_episode_abbr' => 'S{seasonNumber}E{episodeNumber}',
'back_to_episodes' => 'Retour aux épisodes de {podcast}',
'comments' => 'Commentaires',
'activity' => 'Activité',
'description' => 'Description',
'number_of_comments' => '{numberOfComments, plural,
one {# commentaire}
other {# commentaires}
}',
'all_podcast_episodes' => 'Tous les épisodes du podcast',
'back_to_podcast' => 'Revenir au podcast',
'edit' => 'Modifier',
'publish' => 'Publier',
'publish_edit' => 'Modifier la publication',
'unpublish' => 'Dépublier',
'publish_error' => 'Lépisode est déjà publié.',
'publish_edit_error' => 'Lépisode est déjà publié.',
'publish_cancel_error' => 'Lépisode est déjà publié.',
'unpublish_error' => 'Lépisode nest pas publié.',
'delete' => 'Supprimer',
'go_to_page' => 'Voir',
'create' => 'Ajouter un épisode',
'publication_status' => [
'published' => 'Publié',
'scheduled' => 'Planifié',
'not_published' => 'Non publié',
],
'list' => [
'episode' => 'Épisode',
'visibility' => 'Visibilité',
'comments' => 'Commentaires',
'actions' => 'Actions',
],
'form' => [
'warning' =>
'En cas derreur fatale, essayez daugmenter les valeurs de `memory_limit`, `upload_max_filesize` et `post_max_size` dans votre fichier de configuration php puis redémarrez votre serveur web.<br />Les valeurs doivent être plus grandes que le fichier audio que vous souhaitez téléverser.',
'audio_file' => 'Fichier audio',
'audio_file_hint' => 'Sélectionnez un fichier audio .mp3 ou .m4a.',
'info_section_title' => 'Informations épisode',
'info_section_subtitle' => '',
'image' => 'Image de couverture',
'image_hint' =>
'Si vous ne définissez pas dimage, celle du podcast sera utilisée à la place.',
'title' => 'Titre',
'title_hint' =>
'Doit contenir un titre dépisode clair et concis. Ne précisez ici aucun numéro de saison ou dépisode.',
'permalink' => 'Lien permanent',
'season_number' => 'Saison',
'episode_number' => 'Épisode',
'type' => [
'label' => 'Type',
'hint' =>
'- <strong>complet</strong>: épisode complet.<br/>- <strong>bande-annonce</strong>: extrait court, promotionnel du podcast.<br/>- <strong>bonus</strong>: contenu supplémentaire pour le podcast (par exemple des informations sur les coulisses ou des interviews avec les acteurs) ou du contenu promotionnel croisé pour un autre podcast.',
'full' => 'Complet',
'trailer' => 'Bande-annonce',
'bonus' => 'Bonus',
],
'parental_advisory' => [
'label' => 'Avertissement parental',
'hint' => 'Lépisode contient-il un contenu explicite?',
'undefined' => 'non défini',
'clean' => 'Convenable',
'explicit' => 'Explicite',
],
'show_notes_section_title' => 'Notes dépisode (Show Notes)',
'show_notes_section_subtitle' =>
'Jusque 4000 caractères, soyez clairs et concis. Les notes dépisode aident les auditeurs potentiels à le trouver.',
'description' => 'Description',
'description_footer' => 'Pied de description',
'description_footer_hint' =>
'Ce texte est ajouté à la fin de chaque description dépisode, cest un bon endroit pour placer vos liens sociaux par exemple.',
'additional_files_section_title' => 'Fichiers additionels',
'additional_files_section_subtitle' =>
'Ces fichiers pourront être utilisées par dautres plate-formes pour procurer une meilleure expérience à vos auditeurs.<br />Consulter le {podcastNamespaceLink} pour plus dinformations.',
'location_section_title' => 'Localisation',
'location_section_subtitle' => 'De quel lieu cet épisode parle-t-il?',
'location_name' => 'Nom ou adresse du lieu',
'location_name_hint' => 'Ce lieu peut être réel ou fictif',
'transcript' => 'Transcription ou sous-titrage',
'transcript_hint' =>
'Les formats autorisés sont txt, html, srt ou json.',
'transcript_file' => 'Fichier de transcription',
'transcript_file_remote_url' =>
'URL distante pour le fichier de transcription',
'transcript_file_delete' => 'Supprimer le fichier de transcription',
'chapters' => 'Chapitrage',
'chapters_hint' => 'Le fichier doit être en format “JSON Chapters”.',
'chapters_file' => 'Fichier de chapitrage',
'chapters_file_remote_url' =>
'URL distante pour le fichier de chapitrage',
'chapters_file_delete' => 'Supprimer le fichier de chapitrage',
'advanced_section_title' => 'Paramètres avancés',
'advanced_section_subtitle' =>
'Si vous avez besoin dune balise que Castopod ne couvre pas, définissez-la ici.',
'custom_rss' => 'Balises RSS personnalisées pour lépisode',
'custom_rss_hint' => 'Ceci sera injecté dans la balise ❬item❭.',
'block' => 'Lépisode doit être masqué de toutes les plateformes',
'block_hint' =>
'La visibilité de lépisode. Si vous souhaitez retirer cet épisode de lindex Apple, activez ce champ.',
'submit_create' => 'Créer lépisode',
'submit_edit' => 'Enregistrer lépisode',
],
'publish_form' => [
'back_to_episode_dashboard' => 'Retour au tableau de bord de lépisode',
'post' => 'Votre message de publication',
'post_hint' =>
'Écrivez un message pour annoncer la publication de votre épisode. Le message sera diffusé à toutes les personnes qui vous suivent dans le fédiverse et mis en évidence sur la page daccueil de votre podcast.',
'publication_date' => 'Date de publication',
'publication_date_clear' => 'Effacer la date de publication',
'publication_date_hint' =>
'Vous pouvez planifier la sortie de lépisode en saisissant une date de publication future. Ce champ doit être au format YYYY-MM-DD HH:mm',
'publication_method' => [
'now' => 'Maintenant',
'schedule' => 'Planifier',
],
'scheduled_publication_date' => 'Date de publication programmée',
'scheduled_publication_date_clear' => 'Effacer la date de publication',
'scheduled_publication_date_hint' =>
'Vous pouvez planifier la sortie de lépisode en saisissant une date de publication future. Ce champ doit être au format YYYY-MM-DD HH:mm',
'submit' => 'Publier',
'submit_edit' => 'Modifier la publication',
'cancel_publication' => 'Annuler la publication',
'message_warning' => 'Vous navez pas saisi de message pour lannonce de votre épisode!',
'message_warning_hint' => 'Ajouter un message augmente lengagement social, menant à une meilleure visibilité pour votre épisode.',
'message_warning_submit' => 'Publish quand même',
],
'soundbites' => 'Extraits sonores',
'soundbites_form' => [
'title' => 'Modifier les extraits sonores',
'info_section_title' => 'Extraits sonores de lépisode',
'info_section_subtitle' =>
'Ajouter, modifier ou supprimer des extraits sonores',
'start_time' => 'Début',
'start_time_hint' =>
'La première seconde de lextrait sonore, cela peut être un nombre décimal.',
'duration' => 'Durée',
'duration_hint' =>
'La durée de lextrait sonore (en secondes), cela peut être un nombre décimal.',
'label' => 'Libellé',
'label_hint' => 'Texte qui sera affiché.',
'play' => 'Écouter lextrait sonore',
'delete' => 'Supprimer lextrait sonore',
'bookmark' =>
'Cliquez pour récupérer la position actuelle, cliquez à nouveau pour récupérer la durée.',
'submit_edit' => 'Enregistrer tous les extraits sonores',
],
'embeddable_player' => [
'add' => 'Ajouter un lecteur intégré',
'title' => 'Lecteur intégré',
'label' =>
'Sélectionnez une couleur de thème, copiez le code dans le presse-papier, puis collez-le sur votre site internet.',
'clipboard_iframe' => 'Copier le lecteur dans le presse papier',
'clipboard_url' => 'Copier ladresse dans le presse papier',
'dark' => 'Sombre',
'dark-transparent' => 'Sombre transparent',
'light' => 'Clair',
'light-transparent' => 'Clair transparent',
],
];

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'block_lists' => 'Listes de blocage',
'block_lists_form' => [
'blocked_users' => 'Utilisateurs bloqués',
'blocked_users_hint' =>
'Entrez les pseudonymes @utilisateur@domaine séparés par une virgule.',
'blocked_domains' => 'Domaines bloqués',
'blocked_domains_hint' =>
'Entrez les noms de domaine séparés par une virgule.',
'submit' => 'Sauvegarder les listes',
],
];

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'all_podcasts' => 'Tous les podcasts',
'no_podcast' => 'Aucun podcast trouvé',
];

View File

@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'manual_config' => 'Configuration manuelle',
'manual_config_subtitle' =>
'Créez un fichier `.env` qui contient tous vos paramètres puis rafraichissez la page pour continuer linstallation.',
'form' => [
'instance_config' => 'Paramètres de linstance',
'hostname' => 'Nom dhôte',
'media_base_url' => 'Adresse racine des médias',
'media_base_url_hint' =>
'Si vous utilisez un CDN et/ou un service de mesure daudience externe, vous pouvez les définir ici.',
'admin_gateway' => 'Adresse dadministration',
'admin_gateway_hint' =>
'Le chemin pour accéder à ladministration (par exemple https://example.com/cp-admin). Il est défini par défaut à cp-admin, nous vous recommandons de le changer par mesure de sécurité.',
'auth_gateway' => 'Adresse dauthentification',
'auth_gateway_hint' =>
'Le chemin des pages dauthentication (par exemple https://example.fr/cp-auth). Il est défini par défaut à cp-auth, nous vous recommandons de le changer par mesure de sécurité.',
'database_config' => 'Paramètres de base de données',
'database_config_hint' =>
'Castopod doit se connecter à votre base de données MySQL (ou MariaDB). Si vous ne disposez pas de ces informations, merci de contacter ladministrateur du serveur.',
'db_hostname' => 'Nom dhôte (ou IP) de la base de données',
'db_name' => 'Nom de la base de données',
'db_username' => 'Utilisateur de base de données',
'db_password' => 'Mot de passe de base de données',
'db_prefix' => 'Préfixe des tables',
'db_prefix_hint' =>
'Le préfixe des noms de tables de Castopod, laissez la valeur par défaut si vous ne savez pas de quoi il sagit.',
'cache_config' => 'Paramètres de cache',
'cache_config_hint' =>
'Sélectionnez votre gestionnaire de cache préféré. Laissez la valeur par défaut si vous ne savez pas de quoi il sagit.',
'cache_handler' => 'Gestionnaire de cache',
'cacheHandlerOptions' => [
'file' => 'Fichiers',
'redis' => 'Redis',
'predis' => 'Predis',
],
'next' => 'Suivant',
'submit' => 'Terminer linstallation',
'create_superadmin' => 'Créer un compte super-utilisateur',
'email' => 'E-mail',
'username' => 'Identifiant',
'password' => 'Mot de passe',
],
'messages' => [
'createSuperAdminSuccess' =>
'Le compte super-utilisateur a bien été créé. Connectez-vous et commencez à podcaster!',
'databaseConnectError' =>
'Castopod na pas pu se connecter à la base de données. Modifier les paramètres de base de données et essayer à nouveau.',
'writeError' =>
'Impossible de créer/écrire le fichier `.env`. Créez manuellement un fichier `.env` en copiant le modèle `.env.example` fourni avec Castopod.',
],
];

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'info' => 'Informations de mon compte',
'changePassword' => 'Modifier mon mot de passe',
'messages' => [
'wrongPasswordError' =>
'Le mot de passe que vous avez saisi est invalide.',
'passwordChangeSuccess' =>
'Le mot de passe a été modifié avec succès!',
],
];

View File

@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'go_to_website' => 'Visiter le site',
'dashboard' => 'Tableau de bord',
'admin' => 'Accueil',
'podcasts' => 'Podcasts',
'podcast-list' => 'Tous les podcasts',
'podcast-create' => 'Créer un podcast',
'podcast-import' => 'Importer un podcast',
'persons' => 'Intervenants',
'person-list' => 'Tous les intervenants',
'person-create' => 'Nouvel intervenant',
'fediverse' => 'Fédiverse',
'fediverse-blocked_actors' => 'Utilisateurs blockés',
'fediverse-blocked_domains' => 'Domaines blockés',
'users' => 'Utilisateurs',
'user-list' => 'Tous les utilisateurs',
'user-create' => 'Créer un utilisateur',
'pages' => 'Pages',
'page-list' => 'Toutes les pages',
'page-create' => 'Créer une page',
'account' => [
'my-account' => 'Mon compte',
'change-password' => 'Modifier le mot de passe',
'logout' => 'Déconnexion',
],
];

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'back_to_home' => 'Retour à laccueil',
'page' => 'Page',
'all_pages' => 'Toutes les pages',
'create' => 'Créer une page',
'go_to_page' => 'Aller à la page',
'edit' => 'Modifier la page',
'delete' => 'Supprimer la page',
'form' => [
'title' => 'Titre',
'permalink' => 'Lien permanent',
'content' => 'Contenu',
'submit_create' => 'Créer la page',
'submit_edit' => 'Enregistrer',
],
'messages' => [
'createSuccess' => 'La page {pageTitle} a été créée avec succès!',
],
];

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'pageNavigation' => 'Navigation',
'first' => 'Première',
'previous' => 'Précédent',
'next' => 'Suivant',
'last' => 'Dernière',
'older' => 'Plus ancien',
'newer' => 'Plus récent',
'invalidTemplate' => '{0} nest pas un modèle valide.',
'invalidPaginationGroup' => '{0} nest pas un groupe valide.',
];

View File

@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'persons' => 'Intervenants',
'all_persons' => 'Tous les intervenants',
'no_person' => 'Aucun intervenant trouvé!',
'create' => 'Créer un intervenant',
'view' => 'Voir lintervenant',
'edit' => 'Modifier lintervenant',
'delete' => 'Supprimer lintervenant',
'form' => [
'identity_section_title' => 'Identité',
'identity_section_subtitle' => 'Qui intervient sur le podcast',
'image' => 'Photo',
'image_size_hint' =>
'Limage doit être carrée et avoir au moins 400px de largeur et de hauteur.',
'full_name' => 'Nom complet',
'full_name_hint' => 'Le nom complet ou le pseudonyme de lintervenant',
'unique_name' => 'Nom unique',
'unique_name_hint' => 'Utilisé pour les URLs',
'information_url' => 'Adresse dinformation',
'information_url_hint' =>
'URL pointant vers des informations relatives à lintervenant, telle quune page personnelle ou une page de profil sur une plateforme tierce.',
'submit_create' => 'Créer lintervenant',
'submit_edit' => 'Enregistrer lintervenant',
],
'podcast_form' => [
'title' => 'Gérer les intervenants',
'manage_section_title' => 'Gestion',
'manage_section_subtitle' => 'Retirer des intervenants de ce podcast',
'add_section_title' => 'Ajouter des intervenants à ce podcast',
'add_section_subtitle' =>
'Vous pouvez sélectionner plusieurs intervenants et rôles.',
'person' => 'Intervenants',
'person_hint' =>
'Vous pouvez selectionner un ou plusieurs intervenants ayant les mêmes rôles. Les intervenants doivent avoir été préalablement créés.',
'group_role' => 'Groupes et rôles',
'group_role_hint' =>
'Vous pouvez sélectionner aucun, un ou plusieurs groupes et rôles par intervenant.',
'submit_add' => 'Ajouter un/des intervenant(s)',
'remove' => 'Retirer',
],
'episode_form' => [
'title' => 'Gérer les intervenants',
'manage_section_title' => 'Gestion',
'manage_section_subtitle' => 'Retirer des intervenants de cet épisode',
'add_section_title' => 'Ajouter des intervenants à cet épisode',
'add_section_subtitle' =>
'Vous pouvez sélectionner plusieurs intervenants et rôles.',
'person' => 'Intervenants',
'person_hint' =>
'Vous pouvez selectionner un ou plusieurs intervenants ayant les mêmes rôles. Les intervenants doivent avoir été préalablement créés.',
'group_role' => 'Groupes et rôles',
'group_role_hint' =>
'Vous pouvez sélectionner aucun, un ou plusieurs groupes et rôles par intervenant.',
'submit_add' => 'Ajouter un/des intervenant(s)',
'remove' => 'Retirer',
],
'credits' => 'Crédits',
];

View File

@ -1,470 +0,0 @@
<?php
/**
* @copyright 2021 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://podlibre.org/
*/
/* Autogenerated from https://raw.githubusercontent.com/Podcastindex-org/podcast-namespace/main/taxonomy-fr.json on 2021-09-06T09:10:53+00:00 */
return array (
'persons' =>
array (
'creative_direction' =>
array (
'label' => 'Direction de Création',
'roles' =>
array (
'director' =>
array (
'label' => 'Réalisat·eur·rice',
'description' => 'Le directeur est à la tête de toute la production créative, des détails créatifs à la logistique. Il n\'y a généralement qu\'un seul réalisateur pour une production. Ce rôle est principalement vu dans les podcasts de fiction.',
'example' => 'Jenna Knorr pour «Bienvenue à Tinsel Town»',
),
'assistant_director' =>
array (
'label' => 'Réalisat·eur·rice-Assistant·e',
'description' => 'Le directeur adjoint est une liaison entre le réalisateur et le reste de la production, coordonnant souvent la logistique quotidienne de la production. Il peut y avoir plusieurs directeurs adjoints sur un projet. Ce rôle est principalement vu dans les podcasts de fiction.',
'example' => 'William Wright pour «Inn Between»',
),
'executive_producer' =>
array (
'label' => 'Product·eur·rice exécut·if·ive',
'description' => 'Le producteur exécutif est le producteur principal d\'une production. Le rôle peut varier en termes de contrôle créatif, certains «EP» détenant la direction créative d\'un podcast (en fait en assumant le rôle de réalisateur), tandis que d\'autres peuvent adopter une approche plus pratique. Le producteur exécutif a peut-être collecté des fonds pour financer la production, mais ce n\'est pas une responsabilité nécessaire du rôle.',
'example' => 'Jane Rotonda pour «The Larry Meiller Show»',
),
'senior_producer' =>
array (
'label' => 'Premi·er·ère Réalisat·eur·rice',
'description' => 'Le producteur principal est le deuxième producteur le plus ancien de la production (deuxième après le producteur exécutif). Ils supervisent les producteurs et la direction générale et la logistique de l\'ensemble de la production.',
'example' => 'Dr. Jeremy Weisz de «INspired INsider»',
),
'producer' =>
array (
'label' => 'Product·eur·rice',
'description' => 'Le producteur coordonne et exécute la production du podcast. Ces tâches peuvent inclure l\'aide à l\'élaboration de la direction créative d\'un projet, la budgétisation, la recherche, la planification et la supervision de l\'édition et de la production finale.',
'example' => '',
),
'associate_producer' =>
array (
'label' => 'Product·eur·rice Délégué·e',
'description' => 'Le producteur associé remplit une ou plusieurs fonctions de producteur qui lui sont déléguées par un producteur.',
'example' => 'Alex Baumhardt pour «APM Reports»',
),
'development_producer' =>
array (
'label' => 'Product·eur·rice au Développement',
'description' => 'Le producteur de développement coordonne et exécute la direction de création de pré-production d\'un podcast. Leurs responsabilités consistent à trouver de nouvelles idées d\'épisodes et de séries et à travailler avec des écrivains et des chercheurs pour préparer le concept pour la production.',
'example' => '',
),
'creative_director' =>
array (
'label' => 'Direct·eur·rice de la Création',
'description' => 'Le directeur de la création est responsable de la stratégie créative et de l\'exécution de toute une série. Souvent, ce rôle dépasse le contenu pour affecter les œuvres d\'art, la musique, les campagnes marketing, etc.',
'example' => 'Neil Druckmann sur «The Official The Last of Us»',
),
),
),
'cast' =>
array (
'label' => 'Distribution',
'roles' =>
array (
'host' =>
array (
'label' => 'Présentat·eur·rice',
'description' => 'L\'hôte est le maître des cérémonies à l\'antenne du podcast et une présence constante sur chaque épisode (à l\'exception des hôtes invités et des épisodes alternatifs). Les tâches de l\'hôte peuvent inclure la réalisation d\'entrevues, l\'introduction d\'histoires et de segments, la narration, etc. Il peut y avoir plus d\'un hôte par podcast ou épisode.',
'example' => 'Joe Rogan pour «The Joe Rogan Experience»',
),
'co_host' =>
array (
'label' => 'Co-Présentat·eur·rice',
'description' => 'Le co-animateur remplit bon nombre des mêmes tâches que l\'hôte, tout en prenant une présence secondaire sur le podcast.',
'example' => 'Dax Shepard pour «Armchair Expert»',
),
'guest_host' =>
array (
'label' => 'Présentat·eur·rice Exceptionnel·le',
'description' => 'L\'hôte invité remplit toutes les fonctions du rôle d\'hôte traditionnel, mais le fait à titre temporaire. Souvent en une seule apparition ou en une courte période d\'épisodes.',
'example' => 'Erica Kelly sur «Let\'s Taco \'Bout Women and True Crime»',
),
'guest' =>
array (
'label' => 'Invité·e',
'description' => 'L\'invité est une partie extérieure qui fait une apparition à l\'antenne sur un épisode, souvent en tant que participant à un panel ou sujet de l\'interview.',
'example' => 'Lewis Brindley pour «Triforce!"',
),
'voice_actor' =>
array (
'label' => 'Comédien·ne Voix',
'description' => 'The Voice Actor donne une performance dans laquelle ils prêtent leur voix au rôle d\'un personnage dans un épisode de podcast. Alors que la majorité des rôles de doublage seront fictifs, le rôle de doubleur peut également couvrir des reconstitutions de conversations et de personnes réelles.',
'example' => 'Venk Potula pour «Masala Jones»',
),
'narrator' =>
array (
'label' => 'Narrat·eur·rice',
'description' => 'The Narrator donne une performance dans laquelle racontent l\'exposition d\'une histoire fictive ou non fictive, souvent de manière scénarisée. Le narrateur peut également interpréter des voix de personnages dans l\'histoire, à condition qu\'ils conservent toujours le rôle de conteur d\'exposition ou de «voix de Dieu».',
'example' => 'James Harvey Freetly pour «Lakeshore & Limbo»',
),
'announcer' =>
array (
'label' => 'Annonc·eur·euse',
'description' => 'L\'annonceur donne de courtes performances vocales pour l\'introduction du podcast, des sujets d\'épisode, des segments, des invités, des prix, etc. L\'annonceur est secondaire par rapport à l\'hôte du podcast et effectue souvent ses introductions d\'une manière scénarisée et produite.',
'example' => 'Lydia Kapp pour «World Builders Anonymous»',
),
'reporter' =>
array (
'label' => 'Journaliste',
'description' => 'Le journaliste trouve et étudie des nouvelles ou des histoires pour le podcast, interviewant souvent des sujets et menant des recherches. Le journaliste peut également être un poste à l\'antenne, car il transmet les idées de son enquête.',
'example' => '',
),
),
),
'writing' =>
array (
'label' => 'Écriture',
'roles' =>
array (
'author' =>
array (
'label' => 'Aut·eur·rice',
'description' => 'L\'auteur a écrit de la prose ou de la poésie initialement destinée à un texte qui est maintenant lu textuellement à l\'antenne.',
'example' => 'Heiko Martens pour «The Sigmund Freud Files»',
),
'editorial_director' =>
array (
'label' => 'Direct·eur·rice de la Rédaction',
'description' => 'Le directeur de la rédaction dirige tous les départements de l\'organisation derrière le podcast et est responsable de la délégation des tâches aux membres du personnel et de leur gestion. Ils sont l\'éditeur le plus haut placé et sont responsables de la direction, de l\'exactitude et des décisions derrière le contenu de podcast.',
'example' => 'Christopher Twarowski pour «News Beat»',
),
'co_writer' =>
array (
'label' => 'Co-rédact·eur·rice',
'description' => 'Le co-scénariste a écrit un podcast en partenariat avec 1 ou 2 autres écrivains, partageant ainsi le mérite de l\'arc créatif, du dialogue et de la narration.',
'example' => 'Max Eggers dans «THE LIGHTHOUSE»',
),
'writer' =>
array (
'label' => 'Rédact·eur·rice',
'description' => 'The Writer a écrit l\'histoire ou le dialogue d\'un podcast. L\'écrivain est souvent impliqué dans l\'arc créatif d\'une production, mais ce n\'est pas une condition nécessaire. Les écrivains peuvent travailler dans des podcasts fictifs ou non fictifs.',
'example' => '',
),
'songwriter' =>
array (
'label' => 'Aut·eur·rice Composit·eur·rice',
'description' => 'L\'auteur-compositeur a écrit les paroles et / ou la musique d\'accompagnement d\'une chanson originale créée pour le podcast et jouée sur un épisode.',
'example' => 'Ben Lapidus pour «Gay Future»',
),
'guest_writer' =>
array (
'label' => 'Rédact·eur·rice Invité·e',
'description' => 'L\'écrivain invité remplit les fonctions d\'écrivain à titre temporaire, souvent sous la forme d\'un épisode unique ou d\'une courte période d\'épisodes. La distinction entre écrivain et écrivain invité dépend de la décision du podcast lui-même.',
'example' => 'Beth Crane pour «The Unseen Hour»',
),
'story_editor' =>
array (
'label' => 'Rédact·eur·rice en Chef ',
'description' => 'L\'éditeur d\'histoire est responsable de la direction générale de l\'arc de l\'histoire et du développement des personnages d\'un podcast. Souvent vu dans les podcasts de fiction et documentaires.',
'example' => 'Gabrielle Loux pour «The NoSleep Podcast»',
),
'managing_editor' =>
array (
'label' => 'Direct·eur·rice de la Publication',
'description' => 'Le rédacteur en chef supervise et coordonne les activités éditoriales des podcasts, en fournissant à la fois une édition détaillée et la gestion d\'une équipe de rédacteurs et d\'éditeurs pour s\'assurer que les délais et les budgets sont respectés.',
'example' => 'Flora Lichtman pour «Every Little Thing»',
),
'script_editor' =>
array (
'label' => 'Chef·fe-Scénariste',
'description' => 'L\'éditeur de script fournit des notes et des modifications au script d\'enregistrement dans un rôle très pratique. L\'éditeur de script est principalement utilisé dans la fiction, les documentaires et les publicités où les enregistrements scénarisés sont répandus.',
'example' => 'Alex Rioux pour «Bienvenue à Tinsel Town: A Christmas Adventure»',
),
'script_coordinator' =>
array (
'label' => 'Coordinat·eur·rice de scénario',
'description' => 'Le coordinateur du scénario emballe le script final avec des annotations qui reflètent une logistique spécifique et des indices créatifs pour l\'enregistrement et la production.',
'example' => 'Alex Rioux pour «Bienvenue à Tinsel Town: A Christmas Adventure»',
),
'researcher' =>
array (
'label' => 'Enquêt·eur·rice',
'description' => 'Le chercheur coordonne la recherche et la vérification des informations qui peuvent ensuite être utilisées pour le contenu d\'un épisode de podcast, informant souvent la direction d\'une histoire en fonction de nouvelles informations découvertes.',
'example' => 'Dave Grave pour «The Zero Brain Podcast»',
),
'editor' =>
array (
'label' => 'Édit·eur·rice',
'description' => 'L\'éditeur examine et prépare des scripts pour transmettre des informations de manière créative, précise et engageante.',
'example' => '',
),
'fact_checker' =>
array (
'label' => 'Contrôl·eur·euse Qualité',
'description' => 'Le vérificateur de faits examine le contenu d\'un podcast pour vérifier l\'exactitude des faits et vérifie que l\'attribution des citations est correcte. Ils utilisent une variété d\'outils, y compris la recherche de tiers et la sensibilisation individuelle. Souvent, le vérificateur de faits fournira également des notes sur la façon dont la production peut éviter la confusion dans la livraison des informations dans l\'épisode.',
'example' => '',
),
'translator' =>
array (
'label' => 'Traduct·eur·rice',
'description' => 'Le traducteur convertit le contenu d\'une langue à une autre pour le podcast. Cela peut être des interviews, des dialogues, des documents texte, etc. Le travail du traducteur peut être utilisé à l\'antenne ou en coulisses pendant le processus de production / recherche.',
'example' => '',
),
'transcriber' =>
array (
'label' => 'Transcript·eur·rice',
'description' => 'Le transcripteur transforme les dialogues et les signaux audio en texte, qui peut être utilisé en interne pour les processus de production ou affiché publiquement pour les auditeurs.',
'example' => '',
),
'logger' =>
array (
'label' => 'Archiviste',
'description' => 'The Logger examine et documente le contenu et les horodatages de l\'audio brut au service des producteurs et des éditeurs dans le processus de production.',
'example' => '',
),
),
),
'audio_production' =>
array (
'label' => 'Production Audio',
'roles' =>
array (
'studio_coordinator' =>
array (
'label' => 'Coordinat·eur·rice de Studio',
'description' => 'Le coordonnateur de studio gère le studio d\'enregistrement et les techniciens audio travaillant dans le studio au moment de l\'enregistrement.',
'example' => '',
),
'technical_director' =>
array (
'label' => 'Direct·eur·rice Technique',
'description' => 'Le directeur technique supervise l\'enregistrement et la production du podcast car il est impliqué dans les technologies audio, y compris le matériel et les logiciels, et la gestion des rôles impliqués dans ces domaines.',
'example' => 'Adam Raymonda sur «Celebuzz\'d»',
),
'technical_manager' =>
array (
'label' => 'Responsable Technique',
'description' => 'Le directeur technique coordonne une équipe d\'ingénieurs du son et de personnel de studio, dans l\'enregistrement et la production car il est impliqué dans les technologies audio, y compris le matériel et les logiciels.',
'example' => '',
),
'audio_engineer' =>
array (
'label' => 'Ingénieur·e du Son',
'description' => 'L\'ingénieur audio aide à enregistrer et à produire de l\'audio en configurant des environnements d\'enregistrement, en surveillant le recodage et en apportant des ajustements techniques tout au long. L\'ingénieur audio est présent pendant le processus d\'enregistrement, effectuant le plus souvent des ajustements en temps réel. L\'ingénieur du son peut travailler avec des conversations, de la musique, des chansons ou tout autre type d\'audio.',
'example' => 'Peter Leonard de «Startup Podcast»',
),
'remote_recording_engineer' =>
array (
'label' => 'Pren·eur·euse de Son sur Site',
'description' => 'L\'ingénieur d\'enregistrement à distance assure l\'enregistrement correct des conversations ayant lieu à plusieurs endroits sur une ligne téléphonique ou une connexion Internet. L\'ingénieur d\'enregistrement à distance évalue les différentes configurations d\'enregistrement et tente de les réconcilier en un son cohérent, tout en surveillant également le processus d\'enregistrement pour capturer le meilleur son possible.',
'example' => '',
),
'post_production_engineer' =>
array (
'label' => 'Ingénieur·e Post-Production',
'description' => 'L\'ingénieur postproduction évalue les technologies audio et leur application en ce qui concerne les étapes finales de production et de publication.',
'example' => 'Dick Wound pour «Queens Next Door»',
),
),
),
'audio_post_production' =>
array (
'label' => 'Post-Production Audio',
'roles' =>
array (
'audio_editor' =>
array (
'label' => 'Mont·eur·euse Son',
'description' => 'L\'éditeur audio coupe et réorganise l\'audio à des fins de clarté et de narration. L\'éditeur audio peut également effectuer un traitement et un mastering audio généraux.',
'example' => '',
),
'sound_designer' =>
array (
'label' => 'Concept·eur·rice Sonore',
'description' => 'Le Sound Designer crée et compose une variété d\'éléments audio. Ces éléments sont pour la plupart secondaires à la parole, mais un Sound Designer peut éditer / produire des éléments de discours de manière créative d\'une manière artistique.',
'example' => '',
),
'foley_artist' =>
array (
'label' => 'Illustrat·eur·rice Sonore',
'description' => 'Les effets sonores de l\'artiste Foley pour un podcast et peuvent le faire à la fois via un enregistrement physique et un traitement numérique, ou une combinaison des deux.',
'example' => '',
),
'composer' =>
array (
'label' => 'Composit·eur·rice',
'description' => 'Le compositeur écrit une pièce musicale originale (ou plusieurs) qui est jouée sur l\'épisode publié. Le compositeur sera également souvent l\'interprète de ladite pièce musicale.',
'example' => 'Marcus Thorne Bagala de «This American Life»',
),
'theme_music' =>
array (
'label' => 'Musique de Générique',
'description' => 'Theme Music est une pièce musicale qui accompagne le podcast à travers plusieurs épisodes, le plus souvent au début d\'un épisode. Le thème Musique est utilisé pour présenter le podcast en tant que marque. Ce rôle est pour le créateur de la musique du thème.',
'example' => 'Mark Philips de «Startup Podcast»',
),
'music_production' =>
array (
'label' => 'Production Musicale',
'description' => 'Le rôle de production musicale aide à créer de manière créative de la musique dans un rôle distinct de l\'écriture de ladite musique. La production musicale implique souvent des décisions créatives en fonction de la méthode d\'enregistrement de la musique, de l\'arrangement des instruments, de l\'utilisation d\'effets, etc.',
'example' => 'Storm Duper pour «Faking Star Wars Radio»',
),
'music_contributor' =>
array (
'label' => 'Contribution Musicale',
'description' => 'The Music Contributor est le créateur de la musique qui a été utilisée pour le podcast mais pas nécessairement produite spécifiquement pour le podcast. Souvent, un podcast utilisera une pièce musicale existante et créditera le créateur original.',
'example' => 'Bobby Lord de «Startup Podcast»',
),
),
),
'administration' =>
array (
'label' => 'Gestion',
'roles' =>
array (
'production_coordinator' =>
array (
'label' => 'Coordinat·eur·rice de Production',
'description' => 'Le coordonnateur de la production est responsable de la gestion de la logistique du processus de production de l\'enregistrement à la publication, y compris l\'obtention des autorisations et des permis requis, la connexion des différentes équipes de production et d\'enregistrement, la coordination de la création des métadonnées de post-production, la budgétisation, etc.',
'example' => 'Taneya Boyde sur «Prêt pour le changement? »',
),
'booking_coordinator' =>
array (
'label' => 'Programmat·eur·rice',
'description' => 'Le coordonnateur des réservations est chargé de faire venir de nouveaux invités pour les entrevues, y compris la recherche des invités, la planification des entrevues, le matériel d\'accueil et les processus post-publication.',
'example' => 'Meryl Klemow pour «Campfire Sht Show»',
),
'production_assistant' =>
array (
'label' => 'Assistant·e de Production',
'description' => 'L\'assistant de production aide à soutenir un membre de la direction d\'un podcast (souvent un réalisateur ou un producteur), en aidant à les préparer de diverses manières, y compris la planification, la logistique, les communications, etc.',
'example' => 'Wallace Mack pour «The Nod»',
),
'content_manager' =>
array (
'label' => 'Responsable des Contenus',
'description' => 'Le gestionnaire de contenu est responsable de la distribution du contenu d\'un podcast à l\'intérieur et à l\'extérieur de l\'épisode, y compris, mais sans s\'y limiter, les clips, les newsletters, les images, les promotions croisées, etc.',
'example' => 'Kenneth Lee Johnson II pour «Malice Corp Smack Talk»',
),
'marketing_manager' =>
array (
'label' => 'Responsable Marketing',
'description' => 'Le directeur du marketing est responsable de la promotion du contenu d\'un podcast par le biais de diverses stratégies de sensibilisation telles que des campagnes sur les médias sociaux, le développement d\'une présence sur le Web, la gestion des relations publiques et des stratégies de communication et d\'autres techniques créatives pour acquérir et fidéliser les auditeurs.',
'example' => '',
),
'sales_representative' =>
array (
'label' => 'Commercial·e',
'description' => 'Le représentant des ventes est responsable de la monétisation du contenu des balados en gérant et en vendant l\'inventaire publicitaire.',
'example' => '',
),
'sales_manager' =>
array (
'label' => 'Direct·eur·rice Commercial·e',
'description' => 'Le directeur des ventes est responsable de tous les aspects de la monétisation des podcasts, tels que la supervision des représentants des ventes, la gestion de l\'inventaire publicitaire et la conception de stratégies de monétisation via des canaux tels que les partenariats d\'affiliation, la marchandise, les événements en direct et d\'autres stratégies de revenus.',
'example' => '',
),
),
),
'visuals' =>
array (
'label' => 'Illustrations',
'roles' =>
array (
'graphic_designer' =>
array (
'label' => 'Infographiste',
'description' => 'Le graphiste est quelqu\'un qui a créé des visuels personnalisés pour accompagner le podcast de différentes manières.',
'example' => 'Sky Knight pour «The XP Billionaires»',
),
'cover_art_designer' =>
array (
'label' => 'Concept·eur·rice de la Couverture',
'description' => 'Le Cover Art Designer crée la pochette affichée d\'un podcast ou d\'un épisode. Pour plus de clarté, la pochette est l\'image principale (presque toujours carrée) accompagnant le podcast dans les répertoires, tandis que la pochette d\'épisode est affichée de la même manière au niveau de l\'épisode. Ce rôle peut être un concepteur numérique, un artiste, un photographe ou tout autre créatif visuel.',
'example' => '',
),
),
),
'community' =>
array (
'label' => 'Communauté',
'roles' =>
array (
'social_media_manager' =>
array (
'label' => 'Responsable Réseaux Sociaux',
'description' => 'Le gestionnaire de médias sociaux gère les comptes de médias sociaux du podcast, y compris, mais sans s\'y limiter, la création de contenu, la publication, les réponses, la surveillance, etc.',
'example' => 'Tom Joshi-Cale pour «World on a String»',
),
),
),
'misc' =>
array (
'label' => 'Divers',
'roles' =>
array (
'consultant' =>
array (
'label' => 'Consultant',
'description' => 'Un consultant est un poste de tiers où une personne extérieure à l\'organisation travaille sur un projet, offrant souvent une expertise spécifique. Il s\'agit d\'un rôle de modificateur et peut être appliqué à n\'importe quelle zone de travail.',
'example' => 'Ross Wilcock pour «Being Kenzie-Feature Long Immersive Horror»',
),
'intern' =>
array (
'label' => 'Stagiaire',
'description' => 'Un stagiaire est un poste d\'apprenti où quelqu\'un travaille pendant un temps limité au sein d\'une organisation pour acquérir une expérience de travail dans un domaine spécifique. Il s\'agit d\'un rôle de modificateur et peut être appliqué à n\'importe quelle zone de travail.',
'example' => '',
),
),
),
'video_production' =>
array (
'label' => 'Production Vidéo',
'roles' =>
array (
'camera_operator' =>
array (
'label' => 'Cadr·eur·euse',
'description' => 'Un caméraman est chargé de capturer et d\'enregistrer tous les aspects d\'une scène pour le cinéma et la télévision. Ils doivent comprendre les aspects techniques du fonctionnement d\'une caméra, cadrer une photo appropriée en ce qui concerne l\'éclairage et la mise en scène, mettre au point l\'objectif et avoir un œil visuel pour obtenir un look spécifique.',
'example' => '',
),
'lighting_designer' =>
array (
'label' => 'Concept·eur·rice Lumières',
'description' => 'Un concepteur d\'éclairage travaille avec le DP et le directeur pour créer un aspect et une sensation spécifiques d\'une scène en utilisant diverses techniques d\'éclairage. Ils doivent être capables d\'interpréter la direction créative et de lui donner vie.',
'example' => '',
),
'camera_grip' =>
array (
'label' => 'Machiniste',
'description' => 'Une poignée d\'appareil photo est responsable de la construction et de l\'entretien de toutes les pièces d\'un appareil photo et de ses accessoires tels que les trépieds, les grues, les chariots, etc.',
'example' => '',
),
'assistant_camera' =>
array (
'label' => 'Cadr·eur·euse Assistant·e',
'description' => '1st AC est responsable de l\'équipement de la caméra, de la construction des caméras avant le début de chaque journée, de l\'organisation de toutes les pièces et des divers accessoires, du remplacement des objectifs si nécessaire et également de la mise au point pour les opérateurs DP et caméra. Le CA terminera également chaque journée en nettoyant les appareils photo, en écrivant des notes sur l\'appareil photo, en marquant les cartes multimédias et en les remettant au DIT.',
'example' => '',
),
),
),
'video_post_production' =>
array (
'label' => 'Post-Production Vidéo',
'roles' =>
array (
'editor' =>
array (
'label' => 'Rédact·eur·rice en Chef·fe',
'description' => 'Les éditeurs de télévision sont chargés de prendre les séquences et les clips et de les mélanger pour créer la vision et la narration du réalisateur.',
'example' => '',
),
'assistant_editor' =>
array (
'label' => 'Rédact·eur·rice en Chef·fe Adjoint·e',
'description' => 'L\'assistant de montage est chargé de prendre les médias de l\'ensemble, de les intégrer dans le logiciel de montage désigné et d\'organiser les images de manière efficace pour l\'éditeur. Ils doivent également faire très attention pour s\'assurer que l\'audio et la vidéo sont synchronisés et que toutes les séquences du plateau sont correctement ingérées.',
'example' => '',
),
),
),
),
);

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'title' => 'Plateformes',
'home_url' => 'Aller au site {platformName}',
'submit_url' => 'Soumettez votre podcast sur {platformName}',
'visible' => 'Afficher sur la page daccueil du podcast?',
'on_embeddable_player' => 'Afficher sur le lecteur intégré?',
'remove' => 'Supprimer {platformName}',
'submit' => 'Enregistrer',
'messages' => [
'updateSuccess' => 'Les liens ont été enregistrés avec succès!',
'removeLinkSuccess' => 'Le lien a été supprimé.',
'removeLinkError' =>
'Le lien na pas pu être supprimé. Merci dessayer à nouveau.',
],
'description' => [
'podcasting' => 'Lidentifiant du podcast sur cette plate-forme',
'social' => 'Lidentifiant du compte du podcast sur cette plate-forme',
'funding' => 'Message dincitation à laction',
],
];

View File

@ -0,0 +1,239 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'all_podcasts' => 'Tous les podcasts',
'no_podcast' => 'Aucun podcast trouvé!',
'create' => 'Créer un podcast',
'import' => 'Importer un podcast',
'new_episode' => 'Créer un épisode',
'feed' => 'RSS',
'view' => 'Voir le podcast',
'edit' => 'Modifier le podcast',
'delete' => 'Supprimer le podcast',
'see_episodes' => 'Voir les épisodes',
'see_contributors' => 'Voir les contributeurs',
'go_to_page' => 'Aller à la page',
'latest_episodes' => 'Derniers épisodes',
'see_all_episodes' => 'Voir tous les épisodes',
'form' => [
'identity_section_title' => 'Informations sur le Podcast',
'identity_section_subtitle' =>
'Ces champs vous permettent de vous faire remarquer.',
'image' => 'Image de couverture',
'title' => 'Titre',
'handle' => 'Identifiant',
'handle_hint' =>
'Utilisé pour identifier le podcast. Les majuscules, les minuscules, les chiffres et le caractère souligné «_» sont acceptés.',
'type' => [
'label' => 'Type',
'hint' =>
'- <strong>épisodique</strong>: si les épisodes sont destinés à être consommés sans ordre spécifique. Les épisodes les plus récents seront présentés en premier.<br/>- <strong>série</strong>: si les épisodes sont destinés à être consommés dans un ordre séquentiel bien défini. Les épisodes les plus anciens seront présentés en premier.',
'episodic' => 'Épisodique',
'serial' => 'Série',
],
'description' => 'Description',
'classification_section_title' => 'Classification',
'classification_section_subtitle' =>
'Ces champs auront un impact sur votre audience et votre concurrence.',
'language' => 'Langue',
'category' => 'Catégorie',
'category_placeholder' => 'Sélectionner une catégorie…',
'other_categories' => 'Autres catégories',
'parental_advisory' => [
'label' => 'Avertissement parental',
'hint' => 'Contient-il un contenu explicite?',
'undefined' => 'non défini',
'clean' => 'Convenable',
'explicit' => 'Explicite',
],
'author_section_title' => 'Auteur / Autrice',
'author_section_subtitle' => 'Qui gère le podcast?',
'owner_name' => 'Nom du/de la propriétaire',
'owner_name_hint' =>
'Pour usage administratif uniquement. Visible dans le flux RSS public.',
'owner_email' => 'E-mail du/de la propriétaire',
'owner_email_hint' =>
'Utilisé par la plupart des plateformes pour vérifier la propriété du podcast. Visible dans le flux RSS public.',
'publisher' => 'Éditeur / Éditrice',
'publisher_hint' =>
'Le groupe responsable de la création du podcast. Fait souvent référence à la société mère ou au réseau dun podcast. Ce champ est parfois appelé «Auteur».',
'copyright' => 'Droit dauteur',
'location_section_title' => 'Localisation',
'location_section_subtitle' => 'De quel lieu ce podcast parle-t-il?',
'location_name' => 'Nom ou adresse du lieu',
'location_name_hint' => 'Ce lieu peut être réel ou fictif',
'monetization_section_title' => 'Monétisation',
'monetization_section_subtitle' =>
'Gagnez de largent grâce à votre audience.',
'payment_pointer' =>
'Adresse de paiement (Payment Pointer) pour Web Monetization',
'payment_pointer_hint' =>
'Ladresse où vous recevrez de largent grâce à Web Monetization',
'advanced_section_title' => 'Paramètres avancés',
'advanced_section_subtitle' =>
'Si vous avez besoin dune balise que nous navons pas couverte, définissez-la ici.',
'custom_rss' => 'Balises RSS personnalisées pour le podcast',
'custom_rss_hint' => 'Ceci sera injecté dans la balise ❬channel❭.',
'partnership' => 'Partenariat',
'partner_id' => 'ID',
'partner_link_url' => 'URL lien',
'partner_image_url' => 'URL image',
'partner_id_hint' => 'Votre identifiant personnel partenaire',
'partner_link_url_hint' => 'Ladresse générique des liens partenaire',
'partner_image_url_hint' => 'Ladresse générique des images partenaire',
'status_section_title' => 'Statut',
'status_section_subtitle' => 'Vivant ou mort?',
'block' => 'Le podcast doit être masqué sur toutes les plateformes',
'complete' => 'Le podcast naura plus de nouveaux épisodes.',
'lock' => 'Empêcher la copie du podcast',
'lock_hint' =>
'Le but est dindiquer aux autres plates-formes de podcast si elles sont autorisées à importer ce flux. La valeur «oui» signifie que toute tentative dimportation de ce flux dans une nouvelle plateforme doit être rejetée.',
'submit_create' => 'Créer le podcast',
'submit_edit' => 'Enregistrer le podcast',
],
'category_options' => [
'uncategorized' => 'non catégorisé',
'arts' => 'Arts',
'business' => 'Entreprise',
'comedy' => 'Comédie',
'education' => 'Éducation',
'fiction' => 'Fiction',
'government' => 'Gouvernement',
'health_and_fitness' => 'Santé et remise en forme',
'history' => 'Histoire',
'kids_and_family' => 'Enfants et famille',
'Leisure' => 'Loisirs',
'music' => 'Musique',
'news' => 'Actualités',
'religion_and_spirituality' => 'Religion et spiritualité',
'science' => 'Science',
'society_and_culture' => 'Société et Culture',
'sports' => 'Sports',
'technology' => 'Technologie',
'true_crime' => 'Documentaire criminel',
'tv_and_film' => 'Télévision et films',
'books' => 'Livres',
'design' => 'Design',
'fashion_and_beauty' => 'Mode et beauté',
'food' => 'Nourriture',
'performing_arts' => 'Arts du spectacle',
'visual_arts' => 'Arts visuels',
'careers' => 'Carrières',
'entrepreneurship' => 'Entrepreneuriat',
'investment' => 'Investissement',
'management' => 'Gestion',
'marketing' => 'Marketing',
'non_profit' => 'À but non lucratif',
'comedy_interviews' => 'Entretiens comiques',
'improv' => 'Improvisation',
'stand_up' => 'Stand up',
'courses' => 'Cours',
'how_to' => 'Tutoriels',
'language_learning' => 'Apprentissage des langues',
'self_improvement' => 'Développement personnel',
'comedy_fiction' => 'Comédie Fiction',
'drama' => 'Drame',
'science_fiction' => 'Science Fiction',
'alternative_health' => 'Santé alternative',
'fitness' => 'Remise en forme',
'medicine' => 'Médecine',
'mental_health' => 'Santé mentale',
'nutrition' => 'Nutrition',
'sexuality' => 'Sexualité',
'education_for_kids' => 'Éducation pour les enfants',
'parenting' => 'Parentalité',
'pets_and_animals' => 'Animaux de compagnie et animaux',
'stories_for_kids' => 'Histoires pour enfants',
'animation_and_manga' => 'Animation et Manga',
'Automotive' => 'Automobile',
'aviation' => 'Aviation',
'craft' => 'Artisanat',
'games' => 'Jeux',
'hobbies' => 'Loisirs',
'home_and_garden' => 'Maison et jardin',
'video_games' => 'Jeux vidéo',
'music_commentary' => 'Commentaire musical',
'music_history' => 'Histoire de la musique',
'music_interviews' => 'Entretiens musicaux',
'business_news' => 'Actualités économiques',
'daily_news' => 'Actualités quotidiennes',
'entertainment_news' => 'Actualités du divertissement',
'news_commentary' => 'Commentaire dactualité',
'politique' => 'Politique',
'sports_news' => 'Actualités sportives',
'tech_news' => 'Actualités techniques',
'buddhism' => 'Bouddhisme',
'christianity' => 'Christianisme',
'hinduism' => 'Hindouisme',
'islam' => 'Islam',
'judaism' => 'Judaïsme',
'religion' => 'Religion',
'spiritualité' => 'Spiritualité',
'astronomy' => 'Astronomie',
'chemistry' => 'Chimie',
'earth_sciences' => 'Sciences de la Terre',
'life_sciences' => 'Sciences de la vie',
'Mathématiques' => 'Mathématiques',
'natural_sciences' => 'Sciences naturelles',
'nature' => 'Nature',
'physics' => 'Physique',
'social_sciences' => 'Sciences sociales',
'documentary' => 'Documentaire',
'personal_journals' => 'Journaux personnels',
'philosophie' => 'Philosophie',
'places_and_travel' => 'Lieux et voyages',
'relations' => 'Relations',
'baseball' => 'Baseball',
'basketball' => 'Basketball',
'cricket' => 'Cricket',
'fantasy_sports' => 'Sports fantastiques',
'football' => 'Football',
'golf' => 'Golf',
'hockey' => 'Hockey',
'rugby' => 'Rugby',
'running' => 'Course',
'soccer' => 'Football',
'swimming' => 'Natation',
'tennis' => 'Tennis',
'volleyball' => 'Volleyball',
'wilderness' => 'Naturalité',
'wrestling' => 'Lutte',
'after_shows' => 'Après spectacle',
'film_history' => 'Histoire du cinéma',
'film_interviews' => 'Entretiens de films',
'film_reviews' => 'Critiques de films',
'tv_reviews' => 'Critiques TV',
],
'by' => 'Par {publisher}',
'season' => 'Saison {seasonNumber}',
'list_of_episodes_year' => 'Épisodes de {year} ({episodeCount})',
'list_of_episodes_season' =>
'Épisodes de la saison {seasonNumber} ({episodeCount})',
'no_episode' => 'Aucun épisode trouvé!',
'no_episode_hint' =>
'Naviguez au sein des épisodes du podcast episodes grâce à la barre de navigation ci-dessus.',
'follow' => 'Suivre',
'followers' => '{numberOfFollowers, plural,
one {<span class="font-semibold">#</span> abonné·e}
other {<span class="font-semibold">#</span> abonné·e·s}
}',
'posts' => '{numberOfPosts, plural,
one {<span class="font-semibold">#</span> publication}
other {<span class="font-semibold">#</span> publications}
}',
'activity' => 'Activité',
'episodes' => 'Épisodes',
'sponsor_title' => 'Vous aimez le podcast ?',
'sponsor' => 'Soutenez-nous',
'funding_links' => 'Liens de financement pour {podcastTitle}',
'find_on' => 'Trouvez {podcastTitle} sur',
'listen_on' => 'Écoutez sur',
];

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'warning' =>
'Cette procédure peut prendre du temps.<br/>Dans la mesure où la version actuelle ne montre aucune progression durant lexécution, vous ne pourrez voir aucun changement avant la fin.<br/>En cas derreur de timeout, augmentez la valeur de `max_execution_time`.',
'old_podcast_section_title' => 'Le podcast à importer',
'old_podcast_section_subtitle' =>
'Assurez-vous dêtre détenteur des droits du podcast avant de limporter. Copier et diffuser un podcast sans en détenir les droits est assimilable à de la contrefaçon et est passible de poursuites.',
'imported_feed_url' => 'Adresse du flux',
'imported_feed_url_hint' => 'Le flux doit être au format xml ou rss.',
'new_podcast_section_title' => 'Le nouveau podcast',
'advanced_params_section_title' => 'Paramètres avancés',
'advanced_params_section_subtitle' =>
'Si vous ne savez pas à quoi servent ces champs, conservez les valeurs par défaut.',
'slug_field' => [
'label' =>
'Quel champ utiliser pour calculer lidentifiant de lépisode',
'link' => '&lt;link&gt; (adresse)',
'title' => '&lt;title&gt; (titre)',
],
'description_field' => 'Champs pour la description des épisodes',
'force_renumber' => 'Forcer la re-numérotation des épisodes',
'force_renumber_hint' =>
'Utilisez ceci si le podcast à importer ne contient pas de numéros dépisodes mais que vous souhaitez en ajouter pendant limport.',
'season_number' => 'Numéro de saison',
'season_number_hint' =>
'Utilisez ceci si le podcast à importer ne contient pas de numéros de saison mais que vous souhaitez en définir un. Laissez vide sinon.',
'max_episodes' => 'Nombre maximum dépisodes à importer',
'max_episodes_hint' => 'Laissez vide pour importer tous les épisodes',
'lock_import' =>
'Ce flux est protégé. Vous ne pouvez pas limporter. Si en vous êtes le propriétaire, déprotégez-le sur la plate-forme dorigine.',
'submit' => 'Importer le podcast',
];

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'go_to_page' => 'Aller à la page du podcast',
'dashboard' => 'Tableau de bord du podcast',
'podcast-view' => 'Accueil',
'podcast-edit' => 'Modifier le podcast',
'episodes' => 'Épisodes',
'episode-list' => 'Tous les épisodes',
'episode-create' => 'Créer un épisode',
'fediverse' => 'Fédiverse',
'fediverse-block_lists' => 'Listes de blocage',
'analytics' => 'Mesures daudience',
'persons' => 'Intervenants',
'podcast-person-manage' => 'Gestion des intervenants',
'contributors' => 'Contributeurs',
'contributor-list' => 'Tous les contributeurs',
'contributor-add' => 'Ajouter un contributeur',
'platforms' => 'Plate-formes externes',
'platforms-podcasting' => 'Podcasts',
'platforms-social' => 'Réseaux Sociaux',
'platforms-funding' => 'Financement',
'podcast-analytics' => 'Vue densemble',
'podcast-analytics-webpages' => 'Visites des pages web',
'podcast-analytics-locations' => 'Localisations',
'podcast-analytics-unique-listeners' => 'Auditeurs uniques',
'podcast-analytics-players' => 'Lecteurs',
'podcast-analytics-listening-time' => 'Durée découte',
'podcast-analytics-time-periods' => 'Périodes',
];

View File

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'edit_roles' => 'Modifier les rôles de {username}',
'forcePassReset' => 'Forcer la réinitialisation du mot de passe',
'ban' => 'Bloquer',
'unban' => 'Débloquer',
'delete' => 'Supprimer',
'create' => 'Créer un utilisateur',
'view' => 'Informations de {username}',
'all_users' => 'Tous les utilisateurs',
'list' => [
'user' => 'Utilisateurs',
'roles' => 'Rôles',
'banned' => 'Bloqué?',
],
'form' => [
'email' => 'E-mail',
'username' => 'Identifiant',
'password' => 'Mot de passe',
'new_password' => 'Nouveau mot de passe',
'roles' => 'Rôles',
'permissions' => 'Permissions',
'submit_create' => 'Créer un utilisateur',
'submit_edit' => 'Enregistrer',
'submit_password_change' => 'Valider!',
],
'roles' => [
'superadmin' => 'Super-utilisateur',
],
'messages' => [
'createSuccess' =>
'Utilisateur créé avec succès! {username} devra modifier son mot de passe à la première authentification.',
'rolesEditSuccess' =>
'Les rôles de {username} ont été mis à jour avec succès.',
'forcePassResetSuccess' =>
'{username} devra modifier son mot de passe à la prochaine visite.',
'banSuccess' => '{username} a été bloqué.',
'unbanSuccess' => '{username} a été débloqué.',
'banSuperAdminError' =>
'{username} est un super-utilisateur, on ne bloque pas un super-utilisateur comme ça…',
'deleteSuperAdminError' =>
'{username} est un super-utilisateur, on ne supprime pas un super-utilisateur comme ça…',
'deleteSuccess' => '{username} a été supprimé.',
],
];

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
/**
* @copyright 2020 Podlibre
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
* @link https://castopod.org/
*/
return [
'min_dims' =>
'{field} nest pas une image ou na pas la taille minimale requise.',
'is_image_squared' =>
'{field} nest pas une image ou nest pas carré (largeur et hauteur différentes).',
'validate_url' =>
'Le champs {field} doit être une adresse valide (par exemple https://exemple.com/).',
];

View File

@ -17,9 +17,9 @@
<div id="sidebar-backdrop" role="button" tabIndex="0" aria-label="Close" class="fixed z-50 hidden w-full h-full bg-gray-900 bg-opacity-50 md:hidden"></div>
<aside id="admin-sidebar" class="sticky top-0 z-50 flex flex-col max-h-screen transition duration-200 ease-in-out transform -translate-x-full bg-white border-r w-80 holy-grail-sidebar md:translate-x-0">
<?php if (isset($podcast)): ?>
<?= $this->include('admin/podcast/_sidebar') ?>
<?= $this->include('Modules\Admin\Views\podcast\_sidebar') ?>
<?php else: ?>
<?= $this->include('admin/_sidebar') ?>
<?= $this->include('Modules\Admin\Views\_sidebar') ?>
<?php endif; ?>
</aside>
<main class="holy-grail-main">

View File

@ -1,4 +1,4 @@
<?= $this->extend('admin/_layout') ?>
<?= $this->extend('Modules\Admin\Views\_layout') ?>
<?= $this->section('title') ?>
<?= lang('Contributor.add_contributor', [$podcast->title]) ?>

View File

@ -1,4 +1,4 @@
<?= $this->extend('admin/_layout') ?>
<?= $this->extend('Modules\Admin\Views\_layout') ?>
<?= $this->section('title') ?>
<?= lang('Contributor.edit_role', [$user->username]) ?>

Some files were not shown because too many files have changed in this diff Show More